我一直在绕圈子,似乎无法通过谷歌搜索出正确的答案——即使在花了几个小时的时间之后,你还是我的最后一招!
安装程序
在我的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+代码优先+自定义映射,终于到了一个我永远被困的地方,需要一个踢向正确的方向,然后才能重新开始:—)
所以我希望你们能理解上面的内容,并解释我的一些愚蠢的错误/误解!