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实体_C#_Entity Framework_Entity Framework 6 - Fatal编程技术网

C# 无法删除需要父属性的ef实体

C# 无法删除需要父属性的ef实体,c#,entity-framework,entity-framework-6,C#,Entity Framework,Entity Framework 6,我对EF不太满意,所以也许这很简单 我有 public void DeleteLicense(int licenseId) { var entityToDelete = context.Licenses.Find(licenseId); context.Licenses.Remove(entityToDelete); } 我已经检查了它是否找到了正确的许可证,并且上下文是一个ninject(每个请求一个)DbContext 但在运行上述函

我对EF不太满意,所以也许这很简单

我有

    public void DeleteLicense(int licenseId)
    {
        var entityToDelete = context.Licenses.Find(licenseId);
        context.Licenses.Remove(entityToDelete);
    }
我已经检查了它是否找到了正确的许可证,并且上下文是一个ninject(每个请求一个)DbContext

但在运行上述函数后,在上下文上调用SaveChanges()时,我遇到了一个奇怪的错误。我得到:“客户名称字段是必需的。

现在这很奇怪,因为CustomerName在帐户(不是许可证)中,它们是链接的,但仍然存在。下面是更多:

我的账户实体

[Required]
public String CustomerName { get; set; }

public virtual ICollection<License> Licenses { get; set; }
...
我的流畅设置

modelBuilder.Entity<Account>().HasMany(x => x.Licenses)
.WithRequired(x => x.Account).WillCascadeOnDelete(false);
\u accountRepository如下所示

public class EFAccountRepository : EntityFrameworkRepository<Account>
, IAccountRepository

public EFAccountRepository(EvercateContext context) : base(context)
{       
}
public类EFAccountRepository:EntityFrameworkRepository
,IAccountRepository
public EFAccountRepository(EvercateContext):基(context)
{       
}
这是Ninject中的代码,它设置了所有这些

kernel.Bind<EvercateContext>()
.To<EvercateContext>()
.InRequestScope()
.WithConstructorArgument("connectionStringOrName", "EvercateConnection");


kernel.Bind<IAccountRepository>().To<EFAccountRepository>();
kernel.Bind()
.至()
.InRequestScope()
.带有Constructor参数(“连接字符串名称”、“EvercateConnection”);
kernel.Bind().To();
因此,即使我使用工作单元,在运行SaveChanges之前,在这个请求中也不会调用其他任何东西。
是否有任何方法可以查看DbContext在SaveChanges上会做什么,而不实际运行该方法(因为它抛出了DbEntityValidationException

我尝试按照建议重写SaveChanges。 当我这样做时,我发现一个许可证即将被删除(它应该被删除),但我也发现了一个即将创建的帐户

我更改了DeleteLicense,如下所示

    public void DeleteLicense(int licenseId)
    {
        var entityToDelete = context.Licenses.Find(licenseId);
        entityToDelete.Account = null;
        context.Licenses.Remove(entityToDelete);
    }
代码马上就可以工作了。许可证已删除,帐户仍在,但未创建新帐户

但是为什么,我一点也不明白为什么。
这是我与fluent api设置的关系吗?

我可以想象,如果您像这样初始化
许可证
构造函数中的
帐户
导航属性,可能会发生这种奇怪的异常:

public License
{
    Account = new Account();
}
当你打电话的时候

var entityToDelete = context.Licenses.Find(licenseId);
context.Licenses.Remove(entityToDelete);
…那么可能是:

  • 许可证
    实体被加载(无导航属性
    帐户
    )并附加到上下文(状态
    未更改
  • 构造函数设置
    帐户
    导航属性,但它不会附加(状态为
    已分离
  • 当您为
    许可证
    实体调用
    Remove
    时,EF会在内部调用
    DetectChanges
    。它检测到
    License.Account
    正在引用分离的实体,并将其附加到上下文(状态为
    Added
    )。
    许可证的状态更改为
    已删除
  • 当您调用
    SaveChanges
    时,更改跟踪器会找到两个实体:状态为
    已删除的
    许可证
    和状态为
    已添加的
    帐户
  • 验证运行并发现实体
    帐户
    所需的属性
    CustomerName
    null
    (因为只调用了
    帐户
    的默认构造函数)
  • 将引发验证异常
我不确定细节是否正确,但类似的事情可能正在发生


在任何情况下,您都应该删除
帐户=新帐户()许可证
构造函数中选择code>,并检查是否在代码库中的实体构造函数中初始化其他引用导航属性。(初始化空的导航集合是可以的。)这是一个众所周知的奇怪问题的常见来源,这些问题很难找到和理解。

在我的例子中,发生这种情况是因为我的实体有一个
[必需的]
属性,该属性的类型为
int?
,使其可以为空。在检查从数据库返回的模型时,我看到属性有一个值,但由于某种原因,最终保存到数据库的实体在
SaveChanges
过程中被删除了该值。当我将值切换到预期的
int
类型时,所有操作都正常:耸耸肩:

我有一个类似的问题,对我来说,我似乎没有正确地建立父母和孩子在各自班级中的关系

我的修复方法是将下面指定的属性添加到表示其父类Id的属性的子类中

public class Child
{
    [Key, Column(Order = 1)]
    public string Id { get; set; }

    [Key, ForeignKey("Parent"), Column(Order = 2)]  // adding this line fixed things for me
    public string ParentId {get; set;}
}

public class Parent
{
    [Key, Column(Order = 1)]
    public string Id { get; set; }

    ...

    public virtual ICollection<Child> Children{ get; set; }
}
公共类子类
{
[键,列(顺序=1)]
公共字符串Id{get;set;}
[Key,ForeignKey(“父”),Column(Order=2)]//添加此行为我解决了一些问题
公共字符串ParentId{get;set;}
}
公共类父类
{
[键,列(顺序=1)]
公共字符串Id{get;set;}
...
公共虚拟ICollection子项{get;set;}
}

似乎没有什么意义。这个
DeleteLicense
方法是否是您可能无意中创建了
帐户的更大工作单元的一部分?很高兴知道不仅仅是我。我更新了问题中的更多细节。但是总结是:我可以看看SaveChanges不运行它会做什么吗?您可以在
DbContext
中重写
SaveChanges
,并检查
this.ChangeTracker.Entries()
。读到这篇文章,我会怀疑您有一个
帐户=新帐户()在您的
许可证中
实体构造函数。当您调用
…Remove(…)
时,由于在
Remove
内部发生的自动更改检测,该
帐户可能会添加到上下文中(状态为
added
)。因为
帐户
仅使用默认构造函数创建
客户名称
可能是
null
,这导致了验证异常。删除构造函数中的那一行(假设它真的存在)。太棒了!!就这样!如果你把它作为一个答案,我可以接受这个问题。我们每天都学到新的东西。非常感谢您出色的回答!斯劳玛,可以吗
var entityToDelete = context.Licenses.Find(licenseId);
context.Licenses.Remove(entityToDelete);
public class Child
{
    [Key, Column(Order = 1)]
    public string Id { get; set; }

    [Key, ForeignKey("Parent"), Column(Order = 2)]  // adding this line fixed things for me
    public string ParentId {get; set;}
}

public class Parent
{
    [Key, Column(Order = 1)]
    public string Id { get; set; }

    ...

    public virtual ICollection<Child> Children{ get; set; }
}