C# Can';在实体框架中使用AddRange自动生成标识
我不知道这是实体框架的设计选择还是代表我的错误方法,但每当我尝试将范围实体添加到DbSet时,我似乎无法获得自动生成的标识字段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
[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的回答所述_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
返回对象引用的集合,因此可以在集合中看到对对象的任何进一步更改