【发布时间】:2014-07-29 19:00:02
【问题描述】:
我想先说我有一个解决此问题的方法 - 但我今天花了几个小时找出异常的原因,所以我想我会分享
给定域中的两个实体:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Ticket
{
public int Id { get; set; }
public string Name { get; set; }
public virtual User Owner { get; set; }
public int? LockedByUserId { get; set; }
public virtual User LockedByUser { get; set; }
[Timestamp]
public byte[] ETag { get; set; }
}
如下配置:
public class TicketConfiguration : EntityTypeConfiguration<Ticket>
{
public TicketConfiguration()
{
HasRequired(x => x.Owner);
HasOptional(x => x.LockedByUser)
.WithMany()
.HasForeignKey(x => x.LockedByUserId);
Property(x => x.ETag)
.IsConcurrencyToken(true);
}
}
还有这颗种子:
protected override void Seed(DataContext context)
{
var users = context.Set<User>();
var user = new User
{
Name = "Foo"
};
users.AddOrUpdate(x => x.Name, user);
user = users.SingleOrDefault(x => x.Name == "Foo") ?? user;
var tickets = context.Set<Ticket>();
tickets.AddOrUpdate(x=>x.Name, new Ticket
{
Name = "Bar",
Owner = user,
});
}
我有一个例外:
static void Main()
{
var config = new Migrations.Configuration { CommandTimeout = 3600 };
var migrator = new DbMigrator(config);
migrator.Update();
using (var transaction = GetTransaction()) // I've tried with and without transaction
{
var context = new DataContext();
var userId = context.Set<User>().Where(x=>x.Name == "Foo").Select(x=>x.Id).Single();
var ticket = context.Set<Ticket>().Single(x=>x.Name == "Bar");
ticket.LockedByUserId = userId;
context.SaveChanges();
// Exception thrown here 'System.NullReferenceException'
//at System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.GetOtherEndOfRelationship(IEntityWrapper wrappedEntity)
//at System.Data.Entity.Core.Objects.EntityEntry.AddRelationshipDetectedByForeignKey(Dictionary`2 relationships, Dictionary`2 principalRelationships, EntityKey relatedKey, EntityEntry relatedEntry, RelatedEnd relatedEndFrom)
//at System.Data.Entity.Core.Objects.EntityEntry.DetectChangesInForeignKeys()
//at System.Data.Entity.Core.Objects.ObjectStateManager.DetectChangesInForeignKeys(IList`1 entries)
//at System.Data.Entity.Core.Objects.ObjectStateManager.DetectChanges()
//at System.Data.Entity.Core.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()
//at EntityFrameworkFkNull.Program.Main(String[] args) in h:\Projects\Spikes\EntityFrameworkFkNull\EntityFrameworkFkNull\Program.cs:line 27
//at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
//at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
//at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
//at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
//at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
//at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
//at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
//at System.Threading.ThreadHelper.ThreadStart()
transaction.Complete();
}
}
在这里获得完整的解决方案来尝试一下:https://github.com/mvidacovich/EntityFrameworkFkNull
我相信这是因为 Ticket 对 User 有两个不同的外键,但其中只有一个是显式配置的。
据我自己测试,这会影响 EF 5 到 Ef 6。
那么,这就引出了一个问题: 是否预期 EF 会在那里引发异常?
【问题讨论】:
标签: c# entity-framework entity-framework-5 code-first entity-framework-6