EF6 Code First: Using Fluent API to declare a Foreign Key

c# ef-code-first entity-framework

Question

I'm using EF 6 and Code First to develop an app for the insurance sector. Each Account may have multiple Policies, and each Policy may have numerous Transactions in this application. Each Account must also be connected to an Identity (Name, Address, City, etc.). Although it is optional, the Policy has a connection to an Identity as well.

I've discovered that I need to use Fluent API to set the WillCascadeDelete to False for at least one of those paths because of Account -> Identity and Account -> Policy -> Identity.

How do I configure the Account? is my query. Policy and IdentityId. properties with InsuredIdentityId to be foreign keys? Since there shouldn't ever be a need to move from an identity to another class, I have refrained from including any navigation or foreign key fields in the identity class. Is that the reason I'm having trouble understanding this?

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);
    }
}

Are there any decent books or other sources of information for EF Code First, as a side question? I have Julia Lerman's Programming Entity Framework: Code First, which is adequate for the examples it does cover but falls short in terms of the number of scenarios it addresses.

1
5
1/16/2014 5:03:08 PM

Accepted Answer

Firstly, public ICollection<Policy> Policies { get; set; } ought to bepublic virtual ICollection<Policy> Policies { get; set; } .

Only when one side of a relationship is a one and the other is a many are EF foreign key properties able to be mapped. The dependent entity will always use the same primary key as the principal whenever there is a 1:1 or 1:0..1 connection. Because the dependent's foreign key IS its primary key, there can never be a foreign key in these circumstances.

Due to this:

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

The identity's Id and the account's Id will have the same value. In other words, you can totally delete theIdentityId belongings from theAccount entity. I don't know how that code compiles, though, becauseIdentity does not possessAccount navigational capabilities?

Do you really want to approach your Policy mapping in this manner? You claim that a Policy and an Identity may have an optional relationship, however your method is as follows:

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

...indicates that aIdentity can only be directly tied to onePolicy . What's wrong with designing the mapping in this manner?

HasOptional(p => p.InsuredIdentity).WithMany()
    .HasForeignKey(x => x.InsuredIdentityId)
    .WillCascadeOnDelete(false);

With the aforementioned, you are still lacking any navigational properties fromIdentity to Policy You can simply invoke without one..WithMany() being a no-arg But this instructs the database to start up.Identity being the primary,Policy You are the dependent in a typical fk relationship in the database, but you are still unable to browse to aPolicy through anIdentity with code.

Other remarks

The Policy also has a relationship to an Identity, but it is optional.

It follows thatPolicy.InsuredIdentityId ought to be aSystem.Nullable<long> .

5
1/16/2014 5:46:30 PM

Popular Answer

I had a conceptual issue. An Identity may possibly be used more than once, and hence on more than one Account, even if ordinarily it would only apply to one Account (causing me to imagine it as a 1:1). I get what I was searching for if I use the configuration below. It is then up to me to enforce any rules, such as the one-identity-per-account restriction (but as many Policies as are needed)

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

As an alternative, I might have made the Account the optional dependant and the Identity the Primary entity. All Accounts have an Identity, however not all Identities are connected to all Accounts, therefore this would work. Account wouldn't have a separate key anymore.

That doesn't make sense, which is a little worrying.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow