我有以下类要用作Login
对象的属性。我希望这个类没有任何导航属性(因为它只是用于快速检查),如果可能的话,但我愿意允许下面显示的那个。
public class LoginFeature
{
[Key, Column(Order = 0)]
public int RoleId { get; set; } //Role is another table in the db, but not looking for a nav. property or constraint here.
[Key, Column(Order = 1)]
public virtual Login Login { get; set; }
public bool Deny { get; set; }
}
包含这些集合的类是(为了空间而被剥离)
public class Login
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; } //Database ID
public virtual List<LoginFeature> LoginFeatures { get; set; }
}
我的DbContext定义为
public class MyContext : DbContext
{
public DbSet<Login> Logins { get; set; }
public DbSet<LoginFeature> LoginFeatures { get; set; }
}
但是以下测试会产生错误,说明
System.Data.Entity.Infrastructure.DbUpdateException:保存未公开其关系的外键属性的实体时发生错误。 EntityEntries属性将返回null,因为无法将单个实体标识为异常源。通过在实体类型中公开外键属性,可以更轻松地在保存时处理异常。有关详细信息,请参阅InnerException。 ----&GT; System.Data.UpdateException:更新条目时发生错误。有关详细信息,请参阅内部异常 ----&GT; System.Data.SqlClient.SqlException:无法将值NULL插入“RoleId”列,表'TEST.dbo.LoginFeatures';列不允许空值。 INSERT失败。 声明已经终止。
[Test]
public void LoginCanHaveFeatures()
{
using (var ctx = new MyContext())
{
var login = ctx.Logins.FirstOrDefault(x => x.Id == 30);
Assert.IsNotNull(login);
for (int i = 10; i < 15; i++)
{
var feature = new LoginFeature();
feature.Login = login;
feature.RoleId = i;
feature.Deny = true;
login.LoginFeatures.Add(feature);
}
ctx.SaveChanges();
}
}
在EFProf中显示的生成的SQL是
insert [dbo].[LoginFeatures]
([Deny],
[Login_Id])
values (1 /* @0 */,
30 /* @1 */)
这似乎意味着LoginFeature
上的数据注释属性不正确。我正在尝试做什么?
谢谢,
乔
答案 0 :(得分:1)
您无法将导航属性定义为键。仅支持原始属性作为键。所以,你应该像这样定义类:
public class LoginFeature
{
[Key, Column(Order = 0)]
public int RoleId { get; set; }
[Key, Column(Order = 1)]
public int LoginId { get; set; }
public virtual Login Login { get; set; }
public bool Deny { get; set; }
}
映射约定会将LoginId
检测为Login
的外键。可能会发生错误,因为EF确实忽略了您的第二个键属性(因为它在导航属性上),仅使用第一个键RoleId
,默认情况下(对于单个键)假定键在数据库中自动生成(它显然不是,并且没有将其价值发送到数据库。