Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# EF 5-6.1.1中的NullReferenceException具有相同类型的两个导航属性_C#_Entity Framework_Entity Framework 5_Code First_Entity Framework 6 - Fatal编程技术网

C# EF 5-6.1.1中的NullReferenceException具有相同类型的两个导航属性

C# EF 5-6.1.1中的NullReferenceException具有相同类型的两个导航属性,c#,entity-framework,entity-framework-5,code-first,entity-framework-6,C#,Entity Framework,Entity Framework 5,Code First,Entity Framework 6,我想从这一点开始,我有一个解决这个问题的方法——但今天我花了几个小时来找出异常的原因,所以我想与大家分享一下 给定域中的两个实体: 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 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);
    }
}
公共类票证配置:EntityTypeConfiguration
{
公开票证配置()
{
HasRequired(x=>x.Owner);
has可选(x=>x.LockedByUser)
.有很多
.HasForeignKey(x=>x.LockedByUserId);
属性(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,
        });
    }
受保护的覆盖无效种子(DataContext上下文)
{
var users=context.Set();
var user=新用户
{
Name=“Foo”
};
users.AddOrUpdate(x=>x.Name,user);
user=users.SingleOrDefault(x=>x.Name==“Foo”)??用户;
var tickets=context.Set();
tickets.AddOrUpdate(x=>x.Name,新的Ticket
{
Name=“Bar”,
所有者=用户,
});
}
我有一个例外:

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();
        }
    }
static void Main()
{
var config=new Migrations.Configuration{CommandTimeout=3600};
var migrator=新的DbMigrator(配置);
migrator.Update();
使用(var transaction=GetTransaction())//我尝试了使用和不使用事务
{
var context=new DataContext();
var userId=context.Set().Where(x=>x.Name==“Foo”).Select(x=>x.Id).Single();
var ticket=context.Set().Single(x=>x.Name==“Bar”);
ticket.LockedByUserId=用户ID;
SaveChanges();
//此处引发异常“System.NullReferenceException”
//位于System.Data.Entity.Core.Objects.DataClasses.RelatedEnd.GetOtherEndOfRelationship(IEntityRapper包装属性)
//位于System.Data.Entity.Core.Objects.EntityEntry.AddRelationshipDetectedByForeignKey(Dictionary`2关系,Dictionary`2原则关系,EntityKey关系键,EntityEntry关系项,relatedEndFrom)
//位于System.Data.Entity.Core.Objects.EntityEntry.DetectChangesForeignKeys()处
//位于System.Data.Entity.Core.Objects.ObjectStateManager.DetectChangesForeignKeys(IList`1条目)
//位于System.Data.Entity.Core.Objects.ObjectStateManager.DetectChanges()处
//位于System.Data.Entity.Core.Objects.ObjectContext.DetectChanges()处
//位于System.Data.Entity.Internal.InternalContext.DetectChanges(布尔力)
//位于System.Data.Entity.Internal.InternalContext.GetStateEntries(Func`2谓词)
//位于System.Data.Entity.Internal.InternalContext.GetStateEntries()处
//位于System.Data.Entity.Infrastructure.DbChangeTracker.Entries()处
//位于System.Data.Entity.DbContext.GetValidationErrors()处
//位于System.Data.Entity.Internal.InternalContext.SaveChanges()处
//在System.Data.Entity.Internal.LazyInternalContext.SaveChanges()中
//位于System.Data.Entity.DbContext.SaveChanges()处
//在h:\Projects\Spikes\EntityFrameworkFkNull\EntityFrameworkFkNull\Program.cs中的EntityFrameworkFkNull.Program.Main(字符串[]args)处:第27行
//位于System.AppDomain.\u nExecuteAssembly(RuntimeAssembly程序集,字符串[]args)
//位于System.AppDomain.ExecuteAssembly(字符串汇编文件、证据汇编安全性、字符串[]args)
//在Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()上
//位于System.Threading.ThreadHelper.ThreadStart\u上下文(对象状态)
//位于System.Threading.ExecutionContext.RunInternal(ExecutionContext ExecutionContext、ContextCallback回调、对象状态、布尔值preserveSyncCtx)
//在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态,布尔保存SyncCTX)
//在System.Threading.ExecutionContext.Run(ExecutionContext ExecutionContext,ContextCallback回调,对象状态)
//位于System.Threading.ThreadHelper.ThreadStart()处
transaction.Complete();
}
}
获取完整的解决方案,您可以在此处尝试:

我相信这是因为票证对用户有两个不同的外键,但其中只有一个是显式配置的

就我自己测试的情况而言,这会影响EF 5到EF 6


因此,这就引出了一个问题:预计EF会在那里抛出异常吗

解决方法是在票据上有一个“OwnerId”属性。(请参阅github解决方案中的修复分支)

因此,票证变成:

public class Ticket
{
    public int Id { get; set; }

    public string Name { get; set; }

    public int? OwnerId { 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)
            .WithMany()
            .HasForeignKey(x=>x.OwnerId);

        Property(x => x.OwnerId)
            .HasColumnName("Owner_Id");

        HasOptional(x => x.LockedByUser)
            .WithMany()
            .HasForeignKey(x => x.LockedByUserId);

        Property(x => x.ETag)
            .IsConcurrencyToken(true);
    }
}
公共类票证配置:EntityTypeConfiguration
{
公开票证配置()
{
HasRequired(x=>x.Owner)
.有很多
.HasForeignKey(x=>x.OwnerId);
属性(x=>x.OwnerId)
.HasColumnName(“所有者Id”);
has可选(x=>x.LockedByUser)
.有很多
.HasForeignKey(x=>x.LockedByUserId);
属性(x=>x.ETag)
.IsConcurrencyToken(true);
}
}
现在请注意显式的OwnerId。 有关完整(固定)解决方案,请参见以下内容: