w128
w128

Reputation: 4928

Renaming foreign key properties in code first EF classes causes an exception

I have generated several classes using EF6 (code first to an existing SQL Server 2012 database). I'm trying to rename auto-generated properties to adhere to some naming conventions, e.g. from record_number to Number. A ColumnAttribute is then used to provide a mapping.

From my observations, this works as long as I'm not renaming a property that is a foreign key in the SQL Server database. For example, in the following case, if I rename either record_store_id or record_pool_id - both are FK columns - an exception is thrown:

[Table("internal_records")]
public partial class Record
{
    [Key]
    [Column("record_number", Order = 0)]
    public long Number { get; set; }

    [Key]
    [Column("collection_id", Order = 1)]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int CollectionId { get; set; }

    public short record_store_id { get; set; } // Exception if I rename this to e.g. RecordStoreId and add Column("record_store_id")

    [Required]
    [MaxLength(255)]    
    public byte[] record_pool_id { get; set; } // Exception if I rename this to e.g. RecordStoreId and add Column("record_store_id")

    ... // some other properties (not problematic)

    public virtual Collection InternalCollection { get; set; }
    public virtual Pool InternalPool { get; set; }
}

I.e. if I use:

[Column("record_store_id")]
public short RecordStoreId { get; set; }

[Required]
[Column("record_pool_id")]
[MaxLength(255)]    
public byte[] RecordPoolId { get; set; }

an exception will be thrown when using a Linq query:

Unhandled Exception: System.InvalidOperationException: The properties expression 'e => new <>f__AnonymousType0`2(record_store_id = e.RecordStoreId, record_pool_id = e.RecordPoolId)' is not valid. The expression should represent a property: C#: 't => t.MyProperty'  VB.Net: 'Function(t) t.MyProperty'. When specifying multiple properties use an anonymous type: C#: 't => new { t.MyProperty1, t.MyProperty2 }'  VB.Net: 'Function(t) New With { t.MyProperty1, t.MyProperty2 }'.
   at System.Data.Entity.ModelConfiguration.Configuration.DependentNavigationPropertyConfiguration`1.HasForeignKey[TKey](Expression`1 foreignKeyExpression)

I have tried using a ForeignKeyAttribute, but I must have done it incorrectly as that didn't solve my problem.

record_store_id is a PK in internal_stores table (mapped to Store class) and record_pool_id is a PK in internal_pools table (mapped to Pool class).

How can I get this to work?

Upvotes: 0

Views: 3008

Answers (1)

w128
w128

Reputation: 4928

Turns out the problem was in the way OnModelCreating() was being updated when I renamed a property. Originally, the code was:

modelBuilder.Entity<InternalPool>()
    .HasMany(e => e.internal_records)
    .WithRequired(e => e.InternalPool)
    .HasForeignKey(e => new { e.record_store_id, e.record_pool_id })
    .WillCascadeOnDelete(false);

Renaming (via VS refactoring) e.g. record_store_id to RecordStoreId changed the 4th line to something like:

.HasForeignKey(e => new { RecordStoreId = e.record_store_id, e.store_pool_id })

I had to manually change this to reflect my renamed values, i.e. for RecordStoreId and RecordPoolId:

.HasForeignKey(e => new { e.RecordStoreId, e.RecordPoolId })

Upvotes: 1

Related Questions