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
。その値は1
にOrder
あり、1
にありCustomer
ます。
上記のコードを使用してこのキープロパティを変更するにはどうすればよいですか?また、更新を機能させるにはどうすればよいですか?