首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EF6代码优先:使用Fluent API声明外键

EF6代码优先:使用Fluent API声明外键
EN

Stack Overflow用户
提问于 2014-01-16 11:45:48
回答 2查看 15.8K关注 0票数 5

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

由于Account -> Identity和Account ->> Policy -> Identity,我发现需要使用Fluent API将其中至少一个路径的WillCascadeDelete设置为False。

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

代码语言:javascript
复制
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的Programming Entity Framework: Code First,对于它所涵盖的示例来说,这是很好的,但它没有涵盖足够的案例。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-17 01:19:13

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

只有当关系的一端是一端,另一端是多端时,才能映射EF外键属性。任何时候当您有1:1或1:0..1关系时,依赖实体将采用与主体相同的主键。在这些情况下,不能有外键,因为依赖项的外键是它的主键。

因此,对于这个:

代码语言:javascript
复制
HasRequired(a => a.Identity).WithOptional(x => x.Account)

..。帐户的Id将与身份的Id的值相同。也就是说,您可以从Account实体中完全删除IdentityId属性。但是,我不明白代码是如何编译的,因为Identity没有Account导航属性。

当涉及到策略映射时,这真的是您想要的方式吗?你说策略可以与身份有一个可选的关系,但你这样做的方式:

代码语言:javascript
复制
HasOptional(p => p.InsuredIdentity).WithOptionalPrincipal()

一个Identity只能(直接)关联一个Policy的...means。让映射看起来像这样有什么错?

代码语言:javascript
复制
HasOptional(p => p.InsuredIdentity).WithMany()
    .HasForeignKey(x => x.InsuredIdentityId)
    .WillCascadeOnDelete(false);

尽管如此,您仍然没有任何从IdentityPolicy的导航属性。您不需要一个参数,只需以无参数的形式调用.WithMany()即可。但是,这会告诉数据库将Identity设置为主体,将Policy设置为从属,因此您在数据库中具有正常的fk关系,并且您仍然不能在代码中从Policy导航到Identity

其他评论:

策略也与身份有关系,但它是可选的。

这意味着Policy.InsuredIdentityId应该是一个System.Nullable<long>

票数 5
EN

Stack Overflow用户

发布于 2014-01-17 01:47:50

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

代码语言:javascript
复制
public class IdentityConfiguration : EntityTypeConfiguration<Identity>
{
    public IdentityConfiguration()
    {
        HasMany(i => i.Accounts).WithRequired(i => i.Identity).HasForeignKey(a => a.IdentityId);            
    }
}

或者,我可以将身份设置为主要实体,将帐户设置为可选的从属实体。这是可行的,因为所有帐户都有一个身份,但并非所有身份都链接到一个帐户。帐户将不再拥有自己的密钥。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21152966

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档