简体   繁体   中英

EF6 not always generating FK references

I am using Entity Frameworks 6 and when I reverse engineer my schema from the database, I am finding that several FK relationships are not being generated. It's driving me nuts. If I add them in by hand I start getting key violation errors when trying to insert. Take them back out and everything works fine.

Schema: 数据库架构

When I look at my RemarketingCase object I do not see any collections for Addresses, Debtors or Notes and no reference to Asset or Summary. Yet, when I look at either Status objects I have an ICollection of RecordHistories/CaseHistories. I look at either History tables and I have reference to the Status table but no reference to the RemarketingCase table.

This is really irksome as I am trying to deal with object graphs that just don't exist! It is forcing me to handle the add of a RemarketingCase and all it's relationships by doing so one at a time, in the correct order so SQL does not pop a referential integrity error.

Sample with FK reference (generated by EF):

public partial class Status
{
    public Status()
    {
        this.CaseHistories = new List<CaseHistory>();
    }

    public int Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public virtual ICollection<CaseHistory> CaseHistories { get; set; }
}
public class StatusMap : EntityTypeConfiguration<Status>
{
    public StatusMap()
    {
        // Primary Key
        this.HasKey(t => t.Id);

        // Properties
        this.Property(t => t.Title)
            .IsRequired()
            .IsFixedLength()
            .HasMaxLength(15);

        this.Property(t => t.Description)
            .IsRequired()
            .HasMaxLength(50);

        // Table & Column Mappings
        this.ToTable("Status");
        this.Property(t => t.Id).HasColumnName("Id");
        this.Property(t => t.Title).HasColumnName("Title");
        this.Property(t => t.Description).HasColumnName("Description");
    }
}

Sample without FK reference(s) as generated by EF:

public partial class RemarketingCase
{
    public int LoanId { get; set; }
    public int RequestId { get; set; }
    public string VIN { get; set; }
    public int RemarketingCaseId { get; set; }
    public string CaseId { get; set; }
    public string CaseNumber { get; set; }
    public string AssetId { get; set; }
    public System.DateTime Created { get; set; }
    public string CreatedBy { get; set; }
    public Nullable<System.DateTime> Updated { get; set; }
    public string UpdatedBy { get; set; }
}
public class RemarketingCaseMap : EntityTypeConfiguration<RemarketingCase>
{
    public RemarketingCaseMap()
    {
        // Primary Key
        this.HasKey(t => new { t.LoanId, t.RequestId, t.VIN });

        // Properties
        this.Property(t => t.LoanId)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

        this.Property(t => t.RequestId)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);

        this.Property(t => t.VIN)
            .IsRequired()
            .HasMaxLength(25);

        this.Property(t => t.RemarketingCaseId)
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        this.Property(t => t.CaseId)
            .HasMaxLength(50);

        this.Property(t => t.CaseNumber)
            .HasMaxLength(50);

        this.Property(t => t.AssetId)
            .HasMaxLength(50);

        this.Property(t => t.CreatedBy)
            .IsRequired()
            .HasMaxLength(50);

        this.Property(t => t.UpdatedBy)
            .HasMaxLength(50);

        // Table & Column Mappings
        this.ToTable("RemarketingCase");
        this.Property(t => t.LoanId).HasColumnName("LoanId");
        this.Property(t => t.RequestId).HasColumnName("RequestId");
        this.Property(t => t.VIN).HasColumnName("VIN");
        this.Property(t => t.RemarketingCaseId).HasColumnName("RemarketingCaseId");
        this.Property(t => t.CaseId).HasColumnName("CaseId");
        this.Property(t => t.CaseNumber).HasColumnName("CaseNumber");
        this.Property(t => t.AssetId).HasColumnName("AssetId");
        this.Property(t => t.Created).HasColumnName("Created");
        this.Property(t => t.CreatedBy).HasColumnName("CreatedBy");
        this.Property(t => t.Updated).HasColumnName("Updated");
        this.Property(t => t.UpdatedBy).HasColumnName("UpdatedBy");
    }
}

Sample of hand adding references:

public partial class RemarketingCase
{
    public RemarketingCase()
    {
        this.Addresses = new List<Address>();
        this.Debtors = new List<Debtor>();
        this.Notes = new List<Note>();
        this.RecordHistories = new List<RecordHistory>();
        this.CaseHistories = new List<CaseHistory>();
    }

    public int LoanId { get; set; }
    public int RequestId { get; set; }
    public string VIN { get; set; }
    public int RemarketingCaseId { get; set; }
    public string CaseId { get; set; }
    public string CaseNumber { get; set; }
    public string AssetId { get; set; }
    public System.DateTime Created { get; set; }
    public string CreatedBy { get; set; }
    public Nullable<System.DateTime> Updated { get; set; }
    public string UpdatedBy { get; set; }
    // manually added...
    public virtual ICollection<Address> Addresses { get; set; }
    public virtual ICollection<Debtor> Debtors { get; set; }
    public virtual ICollection<Note> Notes { get; set; }
    public virtual ICollection<RecordHistory> RecordHistories { get; set; }
    public virtual ICollection<CaseHistory> CaseHistories { get; set; }
    public virtual Asset Asset { get; set; }
    public virtual Summary Summary { get; set; }
}

And this is the error I get when I hand add the FKs:

Test method AutoPay.Test.Remarketing.DatabaseChange.InsertAsset threw exception: System.Data.Entity.Infrastructure.DbUpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.Data.Entity.Core.UpdateException: An error occurred while updating the entries. See the inner exception for details. ---> System.InvalidOperationException: A dependent property in a ReferentialConstraint is mapped to a store-generated column. Column: 'RemarketingCaseId'.

By changing the DB design a bit, adding the dreaded ID field as the PK, this error went away. While this is a violation of SQL normalization it is what it is. Unfortunately, I've not found a way to make EF deal with a compound PK correctly. (See the comments to my question.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM