3

EF4.2のプロジェクトで次の問題が発生します。EF 5.0(.NET 4.0上)を使用して小さなテストプロジェクトを作成し、問題が新しいバージョンでも同じであるかどうかを確認しました。

サンプルモデル:

public class Order
{
    public int TenantId { get; set; }
    public int OrderId { get; set; }
    public string Name { get; set; }

    public int? CustomerId { get; set; }
    public Customer Customer { get; set; }
}

public class Customer
{
    public int TenantId { get; set; }
    public int CustomerId { get; set; }
    public string Name { get; set; }
}

Fluent APIを使用したコンテキストとマッピング:

public class MyContext : DbContext
{
    public DbSet<Order> Orders { get; set; }
    public DbSet<Customer> Customers { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Order>()
            .HasKey(o => new { o.TenantId, o.OrderId });

        modelBuilder.Entity<Customer>()
            .HasKey(c => new { c.TenantId, c.CustomerId });

        modelBuilder.Entity<Order>()
            .HasOptional(o => o.Customer)
            .WithMany()
            .HasForeignKey(o => new { o.TenantId, o.CustomerId });
    }
}

ここで重要なのは、最初の部分が同時に主キーの一部である複合外部キーでOrder(オプションで)aを参照することです。Customer(TenantId, CustomerId)TenantId(TenantId, OrderId)

私はデータベースと1つを作成しますOrder...

Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());
using (var ctx = new MyContext())
{
    var order = new Order { TenantId = 1, OrderId = 500, Name = "Test Order" };
    ctx.Orders.Add(order);
    ctx.SaveChanges();
}

...そしてそれは機能します。データベーススキーマは期待どおりに見えます(Customer主キーと主キー(TenantId, CustomerId)および従属キーOrderと外部キーとの外部キー関係(TenantId, CustomerId))。

次に、をロードしOrder、新しいを作成し、Customerこれに割り当てOrder、変更を保存して、との間の関係を更新しCustomerますOrder

using (var ctx = new MyContext())
{
    var order = ctx.Orders.Find(1, 500);
    var customer = new Customer { TenantId = 1, CustomerId = 1000,
                                  Name = "Test Customer" };

    order.Customer = customer;
    // order.TenantId is 1 and customer.TenantId is 1

    try
    {
        ctx.SaveChanges();
    }
    catch (Exception e)
    {
        throw;
    }
}

電話SaveChangesをかけるとInvalidOperationException例外が発生します:

プロパティ'TenantId'はオブジェクトのキー情報の一部であり、変更できません。

スタックトレースは次のとおりです。

at System.Data.Objects.EntityEntry.VerifyEntityValueIsEditable(StateManagerTypeMetadata typeMetadata, Int32 ordinal, String memberName)
at System.Data.Objects.EntityEntry.GetAndValidateChangeMemberInfo(String entityMemberName, Object complexObject, String complexObjectMemberName, StateManagerTypeMetadata& typeMetadata, String& changingMemberName, Object& changingObject)
at System.Data.Objects.EntityEntry.EntityMemberChanging(String entityMemberName, Object complexObject, String complexObjectMemberName)
at System.Data.Objects.EntityEntry.EntityMemberChanging(String entityMemberName)
at System.Data.Objects.ObjectStateEntry.System.Data.Objects.DataClasses.IEntityChangeTracker.EntityMemberChanging(String entityMemberName)
at System.Data.Objects.Internal.SnapshotChangeTrackingStrategy.SetCurrentValue(EntityEntry entry, StateManagerMemberMetadata member, Int32 ordinal, Object target, Object value)
at System.Data.Objects.Internal.EntityWrapper`1.SetCurrentValue(EntityEntry entry, StateManagerMemberMetadata member, Int32 ordinal, Object target, Object value)
at System.Data.Objects.DataClasses.EntityReference.UpdateForeignKeyValues(IEntityWrapper dependentEntity, IEntityWrapper principalEntity, Dictionary`2 changedFKs, Boolean forceChange)
at System.Data.Objects.DataClasses.RelatedEnd.Add(IEntityWrapper wrappedTarget, Boolean applyConstraints, Boolean addRelationshipAsUnchanged, Boolean relationshipAlreadyExists, Boolean allowModifyingOtherEndOfRelationship, Boolean forceForeignKeyChanges)
at System.Data.Objects.ObjectStateManager.PerformAdd(IEntityWrapper wrappedOwner, RelatedEnd relatedEnd, IEntityWrapper entityToAdd, Boolean isForeignKeyChange)
at System.Data.Objects.ObjectStateManager.PerformAdd(IList`1 entries)
at System.Data.Objects.ObjectStateManager.DetectChanges()
at System.Data.Objects.ObjectContext.DetectChanges()
at System.Data.Entity.Internal.InternalContext.DetectChanges(Boolean force)
at System.Data.Entity.Internal.InternalContext.GetStateEntries(Func`2 predicate)
at System.Data.Entity.Internal.InternalContext.GetStateEntries()
at System.Data.Entity.Infrastructure.DbChangeTracker.Entries()
at System.Data.Entity.DbContext.GetValidationErrors()
at System.Data.Entity.Internal.InternalContext.SaveChanges()
at System.Data.Entity.Internal.LazyInternalContext.SaveChanges()
at System.Data.Entity.DbContext.SaveChanges()

「鍵の一部」をどこで変更するのかわかりませんTenantId。その値は1Orderあり、1にありCustomerます。

上記のコードを使用してこのキープロパティを変更するにはどうすればよいですか?また、更新を機能させるにはどうすればよいですか?

4

2 に答える 2

1

簡単に見てみると、EFがOrderのTenantIdが変更されたと「考え」ているのに、実際には変更されていない(つまり、値が同じである)バグのようです。http://entityframework.codeplex.com/でこのバグを報告してもよろしいですか?

于 2013-03-14T16:57:44.977 に答える
1

@Pawelの提案によると、Codeplexで発生する可能性のあるバグとして問題を報告しました。

http://entityframework.codeplex.com/workitem/955

現時点では、ナビゲーションプロパティを設定する代わりに、外部キープロパティを直接設定する質問のモデルが機能し、例外をスローしません。

using (var ctx = new MyContext())
{
    var order = ctx.Orders.Find(1, 500);
    var customer = new Customer { TenantId = 1, CustomerId = 1000,
                                  Name = "Test Customer" };

    ctx.Customers.Add(customer);
    order.CustomerId = customer.CustomerId;

    try
    {
        ctx.SaveChanges();
        // No exception here
    }
    catch (Exception e)
    {
        throw;
    }
}
于 2013-03-14T20:31:33.003 に答える