使用实体框架插入时设置Id字段

问题描述 投票:2回答:1

当我试图使用实体框架插入实体(正确的说是整个图形)时,当Id有一些设定值时,我就会出错,例如6.它有这个值是因为它存储在另一个数据库中,我可以为列表中的每个元素手动设定,为子列表中的每个元素手动设定等等。但我必须为每个元素和每个查询做这些事情。我希望有一个独特的全局方式来设置Id字段为零,因为当我试图插入值时,我得到错误。

Cannot insert explicit value for identity column in table 'XXX' when IDENTITY_INSERT is set to OFF.

我想让我的数据库设置Id,并让实体框架忽略Id是否被设置为0以外的任何值。

我试着在OnSaveChanges上做文章,但似乎太晚了,因为当使用Add或AddRange方法时,对象开始被跟踪,我不能在一个列表中为多个对象设置Id。

c# entity-framework asp.net-core entity-framework-core entity-framework-6
1个回答
1
投票

在EF核心3.x,你可以处理 ChangeTracker.Tracked 事件,并重置明确设置自动生成的PK,为每个 Added 像这样的实体(它不需要在外面,你可以自行将db上下文附加到该事件上)。


dbContext.ChangeTracker.Tracked += (sender, e) =>
{
    if (!e.FromQuery && e.Entry.State == EntityState.Added && e.Entry.IsKeySet)
    {
        var pk = e.Entry.Metadata.FindPrimaryKey();
        if (pk.Properties.Count == 1)
        {
            var pkProperty = pk.Properties[0];
            if (pkProperty.ValueGenerated == ValueGenerated.OnAdd &&
                defaultValues.TryGetValue(pkProperty.ClrType, out var defaultValue))
            {
                e.Entry.State = EntityState.Detached;
                e.Entry.CurrentValues[pkProperty] = defaultValue;
                var newEntry = e.Entry.Context.Entry(e.Entry.Entity);
                newEntry.State = EntityState.Added;
            }
        }
    }
};

where defaultValues 是一本带框框的字典 0 (零)值的支持的自动增加属性类型(如果需要的话,你可以添加更多)。

static readonly Dictionary<Type, object> defaultValues = new Dictionary<Type, object>
{
    { typeof(int), default(int) },
    { typeof(long), default(long) },
    { typeof(decimal), default(decimal) },
};

但请注意,这不会修复使用显式FK属性而没有引用导航属性的关系。

© www.soinside.com 2019 - 2024. All rights reserved.