Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.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# EF6 vs Entity Framework Core:插入实体而不将主键(标识)重置为零_C#_Entity Framework_Entity Framework Core - Fatal编程技术网

C# EF6 vs Entity Framework Core:插入实体而不将主键(标识)重置为零

C# EF6 vs Entity Framework Core:插入实体而不将主键(标识)重置为零,c#,entity-framework,entity-framework-core,C#,Entity Framework,Entity Framework Core,EF6:插入一个已经有主键值的实体,并为主键指定一个新值 EF Core:它尝试插入主键的值,但显然失败了,出现了SqlException: 当identity\u insert设置为OFF时,无法在表“资产”中为identity列插入显式值 我找到的解决方法是将PK重置为默认值(0表示int) 例如: Asset asset = new Asset { Id = 3, Name = "Toto",

EF6:插入一个已经有主键值的实体,并为主键指定一个新值

EF Core:它尝试插入主键的值,但显然失败了,出现了SqlException

当identity\u insert设置为OFF时,无法在表“资产”中为identity列插入显式值

我找到的解决方法是将PK重置为默认值(0表示int)

例如:

        Asset asset = new Asset
        {
            Id = 3,
            Name = "Toto",
        };      

        using (AppDbContext context = new AppDbContext())
        {
            asset.Id = 0; // needs to be reset
            context.Assets.Add(asset);
            context.SaveChanges();
        }
我正在将一个解决方案从EF 6迁移到EF Core,我希望避免在插入时手动重置所有ID。上面的例子非常简单,有时我要插入一个完整的图,在我的例子中,这意味着重置图的所有PK和FK

我能想到的唯一自动解决方案是使用反射解析整个图形并重置ID。但我认为这不是很有效


我的问题:如何在全球范围内禁用该行为?

由于EF Core不支持拦截器,我的建议是“破解它”

如果覆盖
SaveChanges
方法,则可以在每次保存时提供此功能,而无需进行大规模重构

public class MyContext : DbContext
{
    //...

    public override int SaveChanges()
    {
        foreach (var dbEntityEntry in ChangeTracker.Entries<Asset>()
                                                   .Where(t => t.State == EntityState.Added))
        {
            dbEntityEntry.Entity.Id = default(int);
        }
        return base.SaveChanges();
    }
}
公共类MyContext:DbContext
{
//...
公共覆盖int SaveChanges()
{
foreach(ChangeTracker.Entries()中的var dbEntityEntry)
.Where(t=>t.State==EntityState.Added))
{
dbEntityEntry.Entity.Id=默认值(int);
}
返回base.SaveChanges();
}
}
这可能会导致每种类型都需要一个循环,或者您可以发挥创意,但一般来说,这将在不对您的业务方法进行大量更改的情况下实现您想要的功能。

不幸的是,目前(从EF Core 2.0.1开始),这种行为是不可控的。我想这应该是EF6的改进,因为它允许您执行身份插入

幸运的是,EF Core构建在基于服务的体系结构上,允许您(尽管不是那么容易)替换几乎所有方面。在这种情况下,负责的服务称为
IValueGenerationManager
,并由类实现。提供上述行为的行是

private static IEnumerable<IProperty> FindPropagatingProperties(InternalEntityEntry entry)    
    => entry.EntityType.GetProperties().Where(    
        property => property.IsForeignKey()    
                    && property.ClrType.IsDefaultValue(entry[property]));

private static IEnumerable<IProperty> FindGeneratingProperties(InternalEntityEntry entry)    
    => entry.EntityType.GetProperties().Where(    
        property => property.RequiresValueGenerator()    
                    && property.ClrType.IsDefaultValue(entry[property]));
然后在
DbContext
派生类中重写
onconfigurang
,并添加以下行:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    // ...
    optionsBuilder.UseEF6CompatibleValueGeneration();
}

问题就这样解决了。

我想说的是,由于重新插入具有重复密钥的对象的糟糕决定,试图让新系统做同样的事情也是一个糟糕的想法。正确的选择是正确地修复所有代码。这不是我的代码,我的工作是移植到ef core,而不是重构。我会不管是谁,我都会把它提出来。我知道一些糟糕的代码,只是想让它正常工作,这不是我想为之工作的公司。如果这是你的情况,我真的很抱歉,我希望有人知道如何解决这个问题。“我的工作是移植,而不是修复”这不是一个好的态度,我给你的建议。@UK知道这会修改现有的条目。我在家里(我不在工作)用一个小项目尝试过它…哇,你是个专业人士。谢谢你救了我的周末!
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    // ...
    optionsBuilder.UseEF6CompatibleValueGeneration();
}