【问题标题】:How to define relationships programmatically in Entity Framework 4.1's Code-First Fluent API如何在 Entity Framework 4.1 的 Code-First Fluent API 中以编程方式定义关系
【发布时间】:2011-07-19 02:09:16
【问题描述】:

我正在玩新的 EF4.1 独角兽之爱。

我试图了解我可以使用 code-first以编程方式定义几个简单 POCO 之间的关系的不同方式。

如何定义以下 =>

  1. 1 Team 有 0-many Users。 (User 在 1 Team 中)
  2. 1 User 有 0 或 1 个 Foo(但 Foo 没有返回到 User 的属性)
  3. 1 User 有 1 UserStuff

【问题讨论】:

    标签: c# .net ef-code-first entity-framework-4.1


    【解决方案1】:

    让我们介绍几个具体的类来说明解决方案:

    public class Account
    {
        public long ID { get; set; }
        public virtual User User { get; set; }
    }
    
    public class User
    {
        public long ID { get; set; }
        public virtual Account Account { get; set; }
        public virtual Team Team { get; set; }
    }
    
    public class Team
    {
        public long ID { get; set; }
        public long CompanyID { get; set; }
    
        public virtual Company Company { get; set; }
        public virtual ICollection<User> Users { get; set; }
    }
    
    public class Company
    {
        public long ID { get; set; }
    }
    

    我正在使用帮助类来使映射类不那么冗长:

    internal abstract class AbstractMappingProvider<T> : IMappingProvider where T : class
    {
        public EntityTypeConfiguration<T> Map { get; private set; }
    
        public virtual void DefineModel( DbModelBuilder modelBuilder )
        {
            Map = modelBuilder.Entity<T>();
    
            Map.ToTable( typeof(T).Name );
        }
    }
    

    现在是映射。让我们先进行“1:1”映射。在我的示例中,用户和帐户是 1:1 相关的,并且共享相同的主键(其中只有一个是身份列,在本例中是 Account.ID)。

    internal class UserMapping : AbstractMappingProvider<User>
    {
        public override void DefineModel( DbModelBuilder modelBuilder )
        {
            base.DefineModel( modelBuilder );
            Map.HasRequired( e => e.Account ).WithRequiredDependent( r => r.User ).WillCascadeOnDelete( true );
        }
    }
    
    internal class AccountMapping : AbstractMappingProvider<Account>
    {
        public override void DefineModel( DbModelBuilder modelBuilder )
        {
            base.DefineModel( modelBuilder );
            Map.HasRequired( e => e.User ).WithRequiredPrincipal( r => r.Account ).WillCascadeOnDelete( true );
        }
    }   
    

    在以下映射中,我们指定一个团队有 (0..n) 个用户,而单个用户恰好在一个团队中(必需)。我们还指定一个团队可以拥有一个公司,但公司不会公开团队列表。

    internal class TeamMapping : AbstractMappingProvider<Team>
    {
        public override void DefineModel( DbModelBuilder modelBuilder )
        {
            base.DefineModel( modelBuilder );
            Map.HasOptional( e => e.Company ).WithMany().HasForeignKey( e => e.CompanyID );
            Map.HasMany( e => e.Users ).WithRequired( r => r.Team );
        }
    }   
    
    internal class CompanyMapping : AbstractMappingProvider<Company>
    {
        public override void DefineModel( DbModelBuilder modelBuilder )
        {
            base.DefineModel( modelBuilder );
        }
    }
    

    希望这会有所帮助!

    【讨论】:

    • 你用 EntityTypeConfiguration 做什么?
    • 我不确定你的意思?传递给 DefineModel 的 DbModelBuilder 实例公开了这种类型的属性,我在 AbstractMappingProvider 上将其公开为 Map 属性。这允许各个派生映射类简单地使用 Map。访问用于定义映射的 EntityTypeConfiguration 实例。
    【解决方案2】:

    这里有您正在寻找的示例:

    public class User
    {
        public int Id { get; set; }
        ...
        public Foo Foo { get; set; }
        public Team Team { get; set; }
        public UserStuff UserStuff { get; set; }
    }
    
    public class Team
    {
        public int Id { get; set; }
        ...
        public ICollection<User> Users { get; set; }
    }
    
    public class Foo
    {
        public int Id { get; set; }
        ...
    }
    
    public class UserStuff
    {
        public int Id { get; set; }
        ...
    }
    
    public class Context : DbContext
    {
        public DbSet<User> Users { get; set; }
        public DbSet<Foo> Foos { get; set; }
        public DbSet<Team> Teams { get; set; }
        public DbSet<UserStuff> UserStuff { get; set; }
    
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<User>()
                .HasRequired(u => u.Team)
                .WithMany(t => t.Users);
    
            modelBuilder.Entity<User>()
                .HasOptional(u => u.Foo)
                .WithRequired();
    
            modelBuilder.Entity<User>()
                .HasRequired(u => u.UserStuff)
                .WithRequiredPrincipal();
        }
    }
    

    【讨论】:

    • modelBuilder.Entity&lt;User&gt;() .HasOptional(u =&gt; u.Foo) .WithRequired();modelBuilder.Entity&lt;User&gt;() .HasOptional(u =&gt; u.Foo) 有什么区别?两者都将允许用户中的 0 或 1 Foo 或?
    猜你喜欢
    • 2012-05-15
    • 2013-12-09
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2016-05-10
    • 1970-01-01
    • 2011-09-10
    • 1970-01-01
    相关资源
    最近更新 更多