C# Can';在实体框架中使用AddRange自动生成标识

C# Can';在实体框架中使用AddRange自动生成标识,c#,entity-framework,orm,entity-framework-6,commit,C#,Entity Framework,Orm,Entity Framework 6,Commit,我不知道这是实体框架的设计选择还是代表我的错误方法,但每当我尝试将范围实体添加到DbSet时,我似乎无法获得自动生成的标识字段 [Table("entities")] public class Entity { [Key] [Column("id")] public long Id { get; set; } [Column("field")] public string Field { get; set; } } var entities = ne

我不知道这是实体框架的设计选择还是代表我的错误方法,但每当我尝试将范围实体添加到DbSet时,我似乎无法获得自动生成的标识字段

[Table("entities")]
public class Entity 
{
    [Key]
    [Column("id")]
    public long Id { get; set; }

    [Column("field")]
    public string Field { get; set; }
}

var entities = new Entity[] 
{
    new Entity() { Field = "A" },
    new Entity() { Field = "B" },
};

_dbContext.Entities.AddRange(entities);
await _dbContext.SaveChangesAsync();

//ids are still default(long) at this point!!
编辑: 下面是更新后的代码,以显示导致问题的原因:枚举。无需向实体类添加其他属性

public class Request
{
    public string Field { get; set; }

    public Entity ToEntity()
    {
        return new Entity() { Field = Field };
    }
}

public async Task<IEnumerable<long>> SaveRequests(IEnumerable<Request> requests)
{
    var entities = requests.Select(r => r.ToEntity()); //not working
    var entities = requests.Select(r => r.ToEntity()).ToArray(); //working

    _dbContext.Entities.AddRange(entities);
    await _dbContext.SaveChangesAsync();

    return entities.Select(e => e.Id);
}
公共类请求
{
公共字符串字段{get;set;}
公共实体实体实体()
{
返回新实体(){Field=Field};
}
}
公共异步任务保存请求(IEnumerable请求)
{
var entities=requests.Select(r=>r.ToEntity());//不工作
var entities=requests.Select(r=>r.ToEntity()).ToArray();//正在工作
_dbContext.Entities.AddRange(Entities);
wait_dbContext.saveChangesSync();
返回实体。选择(e=>e.Id);
}

请尝试此功能,它适用于Int类型列,需要尝试长类型

[Table("entities")]
public class Entity 
{
    [Key]
    [Column("id")]
    // this you need to tell to Ef to use Identity .
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public long Id { get; set; }

    [Column("field")]
    public string Field { get; set; }
}

我首先在EF6中使用数据库,经过一段时间的尝试,我找到了一个可能的解决方案

首先,检查数据库中的表,确保将“ID”列定义为自动递增主键字段,可以使用

ID int IDENTITY(1,1) PRIMARY KEY,
创建表时。一些相关信息可以查看或删除

也可以检查MSSQL IDE中的数据属性,如:

其次,将“ID”列的StoreGeneratedPattern设置为Identity,您可以通过在Visual Studio中打开edmx文件,右键单击表中的数据列并选择Properties,StoreGeneratedPattern设置在Properties窗口中:

相关文章见

完成以上工作后,使用EF AddRange,ID将自动递增,所有工作都很好

public class Entity 
{
    public long Id { get; set; }
    public string Field { get; set; }
}

var entities = new Entity[] 
{
    new Entity() { Field = "A" },
    new Entity() { Field = "B" },
};

_dbContext.Entities.AddRange(entities);

是什么导致了这个问题?数不清的!请查看我问题中的编辑部分,了解解决方案

编辑:将更新后的代码发布到此处作为答案。问题在于我使用枚举的方式。底线是,当您需要立即获得一致的结果时,永远不要相信延迟加载

public class Request
{
    public string Field { get; set; }

    public Entity ToEntity()
    {
        return new Entity() { Field = Field };
    }
}

public async Task<IEnumerable<long>> SaveRequests(IEnumerable<Request> requests)
{
    var entities = requests.Select(r => r.ToEntity()); //not working
    var entities = requests.Select(r => r.ToEntity()).ToArray(); //working

    _dbContext.Entities.AddRange(entities);
    await _dbContext.SaveChangesAsync();

    return entities.Select(e => e.Id);
}
公共类请求
{
公共字符串字段{get;set;}
公共实体实体实体()
{
返回新实体(){Field=Field};
}
}
公共异步任务保存请求(IEnumerable请求)
{
var entities=requests.Select(r=>r.ToEntity());//不工作
var entities=requests.Select(r=>r.ToEntity()).ToArray();//正在工作
_dbContext.Entities.AddRange(Entities);
wait_dbContext.saveChangesSync();
返回实体。选择(e=>e.Id);
}

在Entity Framework Core中,首先使用代码,我通过做两件事来实现这一点:

  • 我将
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    装饰器添加到实体的主键中,正如Yashvier Singh的回答所述
  • 我将新实体对象的主键设置为0
  • 执行这两个步骤后,我不需要将IEnums转换为数组。我只是能够跑:

    _dbContext.Entities.AddRange(entities);
    await _dbContext.SaveChangesAsync();
    

    [Key][DatabaseGenerated(DatabaseGeneratedOption.Identity)]我也有同样的问题,var aData=referenceas.Select(I=>newinternalclass(){/*Id autogen,*/…});db.InternalClass.AddRange(aData);db.SaveChanges();但是无法在aData.FirstOrDefault()(id=0)上检索新id。如果您找到了有关其原因的更多信息,我将永远不会想到这一点。。。你帮我节省了不少时间!你知道为什么会这样吗?这里也一样!这帮了我的忙,但如果有人知道的话,我想理解为什么会发生这种情况。实际上我不知道为什么会发生这种情况,但在LINQ2实体中,为了得到结果,需要使用ToArray()或-比如-Sum()方法对DbSet“执行”每个查询,对吗?我想同样的原则也适用于这里。这对我来说也适用。奇怪的是,在
    AddRange
    中向
    实体添加
    .ToArray()
    是不起作用的,我认为这是可行的,因为
    枚举数
    是不可变的。每次枚举时,它们的行为都是相同的——懒散地计算每个条目。您可以将它们视为生成集合的规范,而不是集合本身。当您在返回行中可枚举的实体上选择
    时,它将再次枚举,您将在每个请求上获得
    .ToEntity()
    的结果,而不是与保存的实体相同的引用。调用
    ToArray
    ToList
    返回对象引用的集合,因此可以在集合中看到对对象的任何进一步更改