EF6 Code First:使用Fluent API声明外键

时间:2014-01-16 03:45:48

标签: c# entity-framework ef-code-first

我正在与EF 6和Code First合作开发与保险行业相关的应用程序。对于此应用程序,每个帐户可以有多个策略,每个策略可以有多个事务。此外,每个帐户必须与身份(姓名,地址,城市等)有关系。该策略还与身份有关系,但它是可选的。

因为帐户 - >身份和帐户 - >>政策 - >身份,我发现我需要使用Fluent API将WillCascadeDelete设置为至少其中一条路径为False。

我的问题是如何将Account.IdentityId和Policy.InsuredIdentityId属性配置为外键?我避免将任何导航/外键字段添加到标识类中,因为永远不应该有理由从标识导航到另一个类。这就是为什么我很难解决这个问题的原因吗?

public class Account
{
    public long Id { get; set; }
    public long IdentityId { get; set; }
    public virtual Identity Identity { get; set; }

    public ICollection<Policy> Policies { get; set; }
}

public class Policy
{
    public long Id { get; set; }

    public long AccountId { get; set; }
    public virtual Account Account { get; set; }

    public bool UseAccountIdentity { get; set; }
    public long InsuredIdentityId { get; set; }
    public virtual Identity InsuredIdentity { get; set; }
}

 public class Identity 
{        
    public long Id { get; set; }

    public string Name { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}

public class AccountConfiguration : EntityTypeConfiguration<Account>
{
    public AccountConfiguration()
    {
        HasRequired(a => a.Identity).WithOptional(x => x.Account).WillCascadeOnDelete(false);
        HasMany(a => a.Policies).WithRequired(p => p.Account).HasForeignKey(p => p.AccountId);
    }
}

public class PolicyConfiguration : EntityTypeConfiguration<Policy>
{
    public PolicyConfiguration()
    {
        HasOptional(p => p.InsuredIdentity).WithOptionalPrincipal().WillCascadeOnDelete(false);
    }
}

作为一个附带问题,EF Code First是否有任何好书或其他参考资料?我有Julia Lerman的编程实体框架:Code First,它适用于它所覆盖的示例,但它没有涵盖足够的案例。

2 个答案:

答案 0 :(得分:5)

首先,public ICollection<Policy> Policies { get; set; }应为public virtual ICollection<Policy> Policies { get; set; }

当关系的一侧是一个,而另一侧是多个时,您只能映射EF外键属性。只要您具有1:1或1:0..1关系,依赖实体将使用与主体相同的主键。在这些情况下,不能有外键,因为从属的外键是其主键。

所以对此:

HasRequired(a => a.Identity).WithOptional(x => x.Account)

...帐户的ID与身份的ID相同。这意味着,您可以从IdentityId实体中完全删除Account属性。但是我不明白该代码是如何编译的,因为Identity没有Account导航属性..?

说到你的政策制图,这真的是你想要的吗?你说一个策略可以与一个身份有一个可选的关系,但是你的方式是这样的:

HasOptional(p => p.InsuredIdentity).WithOptionalPrincipal()

...表示Identity只能(直接)与Policy相关联。HasOptional(p => p.InsuredIdentity).WithMany() .HasForeignKey(x => x.InsuredIdentityId) .WillCascadeOnDelete(false); 。使映射看起来像这样有什么问题?

Identity

根据上述内容,您仍然没有Policy.WithMany()的任何导航属性。你不需要一个,你可以只调用Identity作为无法参考。但是,这告诉数据库将Policy设置为主体,并将Policy设置为依赖关系,因此您在数据库中具有正常的fk关系,但仍然无法导航到Identity来自代码中的Policy.InsuredIdentityId

其他评论:

  

该政策还与身份有关系,但它是可选的。

这意味着System.Nullable<long>应为{{1}}。

答案 1 :(得分:1)

我的问题是概念性的。虽然通常身份只适用于一个帐户(导致我将其可视化为1:1),但理论上,身份可以使用一次以上,因此可以使用多个帐户。如果我使用以下配置,我会得到我想要的。然后由我来执行任何规则,例如身份只能与一个帐户一起使用(但需要尽可能多的策略)

public class IdentityConfiguration : EntityTypeConfiguration<Identity>
{
    public IdentityConfiguration()
    {
        HasMany(i => i.Accounts).WithRequired(i => i.Identity).HasForeignKey(a => a.IdentityId);            
    }
}

或者,我可以将Identity作为主要实体,将Account设置为可选的依赖。这可行,因为所有帐户都有一个身份,但并非所有身份都与帐户相关联。帐户将不再拥有自己的密钥。

这不直观,这有点令人担忧。