[英]Code First EF5: One-to-Zero-or-One relationship is not working
None of the similair questions seem to be able to solve this problem. 类似的问题似乎都无法解决这个问题。 I'm using Entity Framework 5, MVC 4, .NET 4.5 for my web app, designed with VS 2012.
我正在使用Entity Framework 5,MVC 4,.NET 4.5作为我的Web应用程序,使用VS 2012设计。
I have 2 classes that are supposed to be in a parent-child relationship. 我有两个应该是亲子关系的课程。
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
// Other stuff
public int? JoggerId { get; set; }
public virtual Jogger Jogger{ get; set; }
}
and 和
public class Jogger
{
[Key]
public int JoggerId { get; set; }
[Required, ForeignKey("UserId")]
public int UserId { get; set; }
public virtual UserProfile UserProfile { get; set; }
}
With Fluent API: 使用Fluent API:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<UserProfile>()
.HasOptional(x => x.Jogger)
.WithRequired(c => c.UserProfile)
.WillCascadeOnDelete(true);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
base.OnModelCreating(modelBuilder);
}
A User can be a Jogger but can also not be a Jogger ie one User to zero or one Jogger. 用户可以是慢跑者但也可以不是慢跑者,即一个用户零或一个慢跑者。 the relationship looks fine on the EF Powertools edmx view but I cannot get the Foreign key to work with the UserProfile UserId.
EF Powertools edmx视图中的关系看起来很好,但是我无法使用Foreign键来使用UserProfile UserId。
Is my Fluent API wrong or is it my models? 我的Fluent API是错误的还是我的模特? Please help - I am truly stuck!
请帮忙 - 我真的被卡住了!
Your mapping with Fluent API is OK, but remove the UserProfile.JoggerId
and the Jogger.UserId
properties from your model and it should work. 使用Fluent API进行映射是可以的,但是从模型中删除
UserProfile.JoggerId
和Jogger.UserId
属性应该可以正常工作。 The reason is that Entity Framework uses the primary key of Jogger
as the foreign key to UserProfile
, so you don't need to (and can't) have a separate foreign key property. 原因是Entity Framework使用
Jogger
的主键作为UserProfile
的外键,因此您不需要(也不能)具有单独的外键属性。 This kind of one-to-one relationship is called " Shared Primary Key Association ". 这种一对一的关系称为“ 共享主键关联 ”。
Edit 编辑
Keep in mind that the primary key of Jogger
(as the dependent of the relationship) is not autogenerated in the database, only the primary key of UserProfile
is autogenerated (as the principal of the relationship). 请记住,
Jogger
的主键(作为关系的依赖) 不是在数据库中自动生成的,只有UserProfile
的主键是自动生成的(作为关系的主体)。
The way how you would insert a UserProfile
or a Jogger
or both into the database is the following: 将
UserProfile
或Jogger
或两者插入数据库的方式如下:
If you want to insert a UserProfile
without a Jogger
just add it to the context: 如果要在没有
Jogger
的情况下插入UserProfile
,只需将其添加到上下文中:
using (var context = new MyContext()) { var newUserProfile = new UserProfile(); // no key needs to be supplied, the DB will take care context.UserProfiles.Add(newUserProfile); context.SaveChanges(); }
If you want to insert a UserProfile
with a Jogger
in a single step: 如果要在一个步骤中插入带有
Jogger
的UserProfile
:
using (var context = new MyContext()) { var newUserProfile = new UserProfile { Jogger = new Jogger() }; // no key needs to be supplied, neither for UserProfile // nor for Jogger, the DB will take care context.UserProfiles.Add(newUserProfile); context.SaveChanges(); }
If you want to insert a Jogger
(and it must be a Jogger
for an existing UserProfile
): 如果要插入
Jogger
(它必须是现有UserProfile
的Jogger
):
using (var context = new MyContext()) { var newJogger = new Jogger { JoggerId = someExistingUserProfileId }; // a valid key needs to be supplied, otherwise you would violate a FK // constraint in the database context.Joggers.Add(newJogger); context.SaveChanges(); }
Edit 2 编辑2
For your use case where you don't have the UserId
directly available but the Name
(as authenticated user) instead you must load the key or the UserProfile
first from the database: 对于您没有
UserId
直接可用但Name
(作为经过身份验证的用户)的用例,您必须首先从数据库加载密钥或UserProfile
:
// we are in an ASP.NET MVC controller action here
using (var context = new MyContext())
{
string userName = User.Identity.Name;
int? userId = context.UserProfiles
.Where(u => u.Name == userName)
.Select(u => (int?)u.UserId)
.SingleOrDefault();
if (userId.HasValue)
{
var newJogger = new Jogger { JoggerId = userId.Value };
context.Joggers.Add(newJogger);
context.SaveChanges();
}
}
Or loading the UserProfile
will work as well: 或者加载
UserProfile
也可以:
using (var context = new MyContext())
{
string userName = User.Identity.Name;
UserProfile userProfile = context.UserProfiles
.Where(u => u.Name == userName)
.SingleOrDefault();
if (userProfile != null)
{
userProfile.Jogger = new Jogger();
// I believe you don't need to set the JoggerId key now,
// I'm not sure though
context.SaveChanges();
// Change tracking recognizes the new Jogger
// no context.Joggers.Add is required
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.