2013-09-23 33 views
0

我有以下我希望用作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.Inf rastructure.DbUpdateException:保存不为其关系提供外键属性的实体时发生错误。 EntityEntries属性将返回null,因为单个实体不能被识别为异常的来源。通过在您的实体类型中公开外键属性,可以更轻松地处理保存时的异常。有关详细信息,请参阅InnerException。 ----> System.Data.UpdateException:更新条目时发生错误。详情请参阅内部例外。 ----> 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(); 
     } 
    } 

的SQL正在EFProf作为表演产生是

insert [dbo].[LoginFeatures] 
    ([Deny], 
    [Login_Id]) 
values (1 /* @0 */, 
    30 /* @1 */) 

这似乎意味着,该数据注解属性上LoginFeature是不正确的。我正在尝试做什么?

感谢,

回答

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,并且默认情况下(对于单个键)假定该键是在数据库中自动生成的(显然它不是't)并且不会将其值发送到数据库。