没有双连接表,实体框架的多对多关系

时间:2010-09-22 18:01:52

标签: c# entity-framework entity-framework-4

我有以下设置(工作正常)。使用CodeFirst(CTP4)。

模板具有影响列表,每个影响都为特征赋予一个值。

public class Template
{
    public virtual int Id { get; set; }
    public virtual ICollection<Influence> Influences { get; set; }
}

public class Influence
{
    public virtual int Id { get; set; }
    public virtual Trait Trait { get; set; }
    public virtual int Value { get; set; }
}

public class Trait
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
}

模板配置如下。

public class TemplateConfiguration : EntityConfiguration<Template>
{
    public TemplateConfiguration()
    {
        HasKey(o => o.Id);
        Property(o => o.Id).IsIdentity();

        HasMany(o => o.Influences).WithRequired()
            .Map("templates.influences",
            (template, influence) => new {
                Template = template.Id,
                Influence = influence.Id
            });
        MapSingleType(o => new {
            o.Id
        });
    }
}

有效,但我宁愿避免额外的'影响'表。从本质上讲,“影响”只是一个对象,并不需要成为它们的中心存储。事实上,如果没有适合他们的中心表,我试图接近的设计更有利。

我希望为Template表设置这样的场景......基本上影响没有自己的表,它们只是被Trait / Value映射使用它们。 / p>

    public TemplateConfiguration()
    {
        HasMany(u => u.Influences).WithMany()
            .Map("templates.influences",
            (template, influence) => new {
                Template = template.Id,
                Trait = influence.Trait.Id,
                Value = influence.Value
            });

        MapSingleType(c => new {
            c.Id
        }).ToTable("templates");
    }

当我尝试这样做时,我在模板映射上得到了例外。

  
    

未处理System.InvalidOperationException

         

给定的表达式包含无法识别的模式'influence.Trait.Id'。

  

如果需要,以下是整个项目代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Objects;
using System.Data.EntityClient;
using System.Data.Entity.ModelConfiguration;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;

namespace EFTest
{
    class Program
    {
        static void Main(string[] args)
        {
                    Database.SetInitializer<SampleDataContext>(new AlwaysRecreateDatabase<SampleDataContext>());
            var builder = new ModelBuilder();

            builder.Configurations.Add(new TraitConfiguration());
            builder.Configurations.Add(new InfluenceConfiguration());
            builder.Configurations.Add(new TemplateConfiguration());

            var model = builder.CreateModel();

            using (var context = new SampleDataContext(model))
            {
                var traits = new List<Trait>
                {
                    new Trait { Name = "Years" },
                    new Trait { Name = "Days" }
                };
                traits.ForEach(x => { context.Traits.Add(x); });
                context.SaveChanges();

                var templates = new List<Template>
                {
                    new Template
                    {
                        Influences = new List<Influence>
                        {
                            new Influence
                            {
                                Trait = context.Traits.Single( i => i.Name == "Years" ),
                                Value = 5
                            },
                            new Influence
                            {
                                Trait = context.Traits.Single( i => i.Name == "Days" ),
                                Value = 15
                            }
                        }
                    }
                };
                templates.ForEach(x => { context.Templates.Add(x); });
                context.SaveChanges();
            }
        }
    }

    public class SampleDataContext : DbContext
    {
        public SampleDataContext(DbModel model)
            : base(model)
        {
        }

        public DbSet<Trait> Traits { get; set; }
        public DbSet<Influence> Influences { get; set; }
        public DbSet<Template> Templates { get; set; }
    }

    public class Trait
    {
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
    }

    public class TraitConfiguration : EntityConfiguration<Trait>
    {
        public TraitConfiguration()
        {
            HasKey(o => o.Id);
            Property(o => o.Id).IsIdentity();

            MapSingleType(o => new {
                o.Id,
                o.Name
            });
        }
    }

    public class Influence
    {
        public virtual int Id { get; set; }
        public virtual Trait Trait { get; set; }
        public virtual int Value { get; set; }
    }

    public class InfluenceConfiguration : EntityConfiguration<Influence>
    {
        public InfluenceConfiguration()
        {
            HasKey(o => o.Id);
            Property(o => o.Id).IsIdentity();

            HasRequired(o => o.Trait);
            Property(o => o.Value);

            MapSingleType(o => new {
                o.Id,
                Trait = o.Trait.Id,
                o.Value
            });
        }
    }

    public class Template
    {
        public virtual int Id { get; set; }
        public virtual ICollection<Influence> Influences { get; set; }
    }

    public class TemplateConfiguration : EntityConfiguration<Template>
    {
        public TemplateConfiguration()
        {
            HasKey(o => o.Id);
            Property(o => o.Id).IsIdentity();

            HasMany( o => o.Influences).WithRequired()
                .Map("templates.influences", 
                (template, influence) => new {
                    Template = template.Id,
                    Influence = influence.Id
                });
            MapSingleType(o => new {
                o.Id
            });
        }
    }
}

1 个答案:

答案 0 :(得分:1)

好的,新的一天新想法。

我现在已经安装了CTP4并获得了相同的4个表。

产生多对多关系的原因是模型不知道影响只会被一个模板使用。然后你必须告诉它:

public class Influence
 {
    public virtual int Id { get; set; }
    public virtual Trait Trait { get; set; }
    public virtual int Value { get; set; }
    public virtual Template Template { get; set; }
 } 

    public InfluenceConfiguration()
    {
        HasKey(o => o.Id);
        Property(o => o.Id).IsIdentity();
        Property(o => o.Value);

        MapSingleType(o => new
        {
            o.Id,
            Trait = o.Trait.Id,
            o.Value,
            Template = o.Template.Id
        });
    } 

影响表将如下所示:

CREATE TABLE [dbo].[Influences](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Template] [int] NULL,
    [Trait] [int] NULL,
    [Value] [int] NOT NULL,
PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[Influences]  WITH CHECK ADD  CONSTRAINT [Influence_Template] FOREIGN KEY([Template])
REFERENCES [dbo].[Templates] ([Id])
GO

ALTER TABLE [dbo].[Influences] CHECK CONSTRAINT [Influence_Template]
GO

ALTER TABLE [dbo].[Influences]  WITH CHECK ADD  CONSTRAINT [Influence_Trait] FOREIGN KEY([Trait])
REFERENCES [dbo].[Traits] ([Id])
GO

ALTER TABLE [dbo].[Influences] CHECK CONSTRAINT [Influence_Trait]
GO