代码之家  ›  专栏  ›  技术社区  ›  Dav

带抽象类的EF4 TPT-定义关系

  •  2
  • Dav  · 技术社区  · 14 年前

    我一直在绕圈子,似乎无法通过谷歌搜索出正确的答案——即使在花了几个小时的时间之后,你还是我的最后一招!

    安装程序

    在我的Web应用程序中,我希望允许用户使用不同的身份验证机制来访问他们的帐户。除了通常的用户/密码之外,我还想让他们使用谷歌的OpenID、雅虎的OpenID,甚至Facebook。这似乎很容易映射到类中:一个抽象的 Account 用几个 <something>Account 从继承一些基本属性的类 账户 . 我从以下两个课程开始:

    public abstract class Account
    {
        public int Id { get; set; }
        public int OwnerId { get; set; }
    
        public virtual Person Owner { get; set; }
    }
    
    public class OpenIdAccount : Account
    {
        public string Identifier { get; set; }
    }
    

    作为一个完美主义者,在我的日常工作中做了大量的数据库开发,我决定每种类型的表(TPT)是最理想的选择。由于EF4默认使用TPH,因此在我定义的内容的dbContext方面:

    public class MySampleDb : DbContext
    {
        public DbSet<Person> People { get; set; }
        public DbSet<Account> Accounts { get; set; }
        public DbSet<OpenIdAccount> OpenIdAccounts { get; set; }
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Account>().MapHierarchy(a => new
            {
                a.Id, 
                a.OwnerId
            }).ToTable("Account");
    
            modelBuilder.Entity<OpenIdAccount>().MapHierarchy(oid => new
            {
                oid.Id,
                oid.Identifier
            }).ToTable("OpenIdAccount");
        }
    }
    

    现在,我希望从一些简单的测试开始,并认为在每次运行时播种数据库是获得一致数据的好方法:

    protected override void Seed(MySampleDb context)
    {
        Person johns = new Person
        {
            Id = 1,
            Nickname = "John Skeet"
        };
    
        OpenIdAccount google = new OpenIdAccount
        {
            Id = 2,
            OwnerId = 1,
            Identifier = "https://www.google.com/accounts/o8/id?id=AItOawnmUz4e6QIn9mgd98WMAbnzC25sji5lpSM"
        };
    
        context.People.Add(johns);
        context.Accounts.Add(google);
        context.SaveChanges();
    }
    

    (不知道为什么,但dbContext似乎从未尝试用上面的数据填充我的数据库,直到我明确地调用 .SaveChanges() …有什么想法吗?)

    问题

    在数据库中,ef没有定义 账户 OpenIdAccount . 这是第一个警告标志,有些事情不对劲;当然OpenIDaccount应该 Id 定义为同时指向account.id的pk和fk?

    我得到以下信息 UpdateException 当.NET尝试执行时 Savechange() :

    跨实体或关联共享的值 在多个位置生成。检查一下 映射不会将EntityKey拆分为多个 存储生成的列。

    下一步

    今天是我使用EF4和代码优先开发的第一天。我花了很多时间阅读了EF4+代码优先+自定义映射,终于到了一个我永远被困的地方,需要一个踢向正确的方向,然后才能重新开始:—)

    所以我希望你们能理解上面的内容,并解释我的一些愚蠢的错误/误解!

    1 回复  |  直到 14 年前
        1
  •  4
  •   Morteza Manavi    14 年前








    System.ComponentModel.DataAnnotations

    public abstract class Account 
    {
        [StoreGenerated(StoreGeneratedPattern.None)]
        public int Id { get; set; }
        public int OwnerId { get; set; }
        public virtual Person Owner { get; set; }
    }
    


    modelBuilder.Entity<Account>().Property(a => a.Id)
        .StoreGeneratedPattern = System.Data.Metadata.Edm.StoreGeneratedPattern.None;
    



    modelBuilder.Entity<Account>().MapHierarchy(a => new {
        a.Id,
        a.OwnerId,
    })
    .ToTable("Accounts");
    
    modelBuilder.Entity<OpenIdAccount>().MapHierarchy(o => new {
        o.Id,
        o.OwnerId,
        o.Identifier
    })
    .ToTable("OpenIdAccounts");
    



    How to choose an Inheritance Strategy

    推荐文章