【发布时间】:2010-11-22 09:31:25
【问题描述】:
我一直在绕圈子,似乎无法在谷歌上找到正确的答案 - 即使在这上面花了几个小时,所以你是我最后的选择!
设置
在我的网络应用程序中,我想让用户使用不同的身份验证机制来访问他们的帐户。除了通常的用户/密码之外,我还想让他们能够使用 Google 的 OpenId、Yahoo 的 OpenId 甚至 Facebook。这似乎很容易映射到类中:一个抽象的Account 与几个<something>Account 类继承了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 没有定义Account 和OpenIdAccount 之间的任何关系。这是出现问题的第一个警告信号。 OpenIdAccount 是否应该将其 Id 定义为指向 Account.Id 的 PK 和 FK?
两个
当 .net 尝试执行 .SaveChanges() 时,我得到以下 UpdateException:
跨实体或关联共享的值 在多个位置生成。检查 映射不会将 EntityKey 拆分为多个 存储生成的列。
后续步骤
今天是我使用 EF4 和代码优先开发的第一天。花了很多时间阅读有关 EF4 + 代码优先 + 自定义映射的信息后,我到了一个永久卡住的地步,需要朝着正确的方向前进,然后才能重新开始:-)
所以我希望你们能够理解上述内容并解释我的一些愚蠢的错误/误解!
【问题讨论】:
标签: .net entity-framework ef4-code-only