无法使用 Entity Framework 中的 AddRange 自动生成 IDENTITY
Can't auto-generate IDENTITY with AddRange in Entity Framework
我不知道这是 Entity Framework 的设计选择还是代表我的错误方法,但每当我尝试将 AddRange 实体添加到 DbSet 时,我似乎无法获得自动 -生成的 IDENTITY 字段。
[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);
}
请试试这个,它适用于 Int 类型列,需要在 long 类型上尝试。
[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; }
}
我在 EF 6 中使用数据库优先,在尝试了一段时间后,我找到了一个可能的解决方案。
首先,检查数据库中的 Table,确保将 'ID' 列定义为自增主键字段,可以使用类似
ID int IDENTITY(1,1) PRIMARY KEY,
创建您的 table 时。一些相关资料可以看here1 or here2.
或者您可以在 MSSQL IDE 中检查数据属性,例如:
其次,将'ID'列的StoreGeneratedPattern设置为Identity,你可以通过在Visual Studio,右击table和select属性中的Data Column,StoreGeneratedPattern设置在属性Window:
部分相关文章见here。
完成上述操作后,使用 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);
是什么导致了这个问题?可枚举!查看我问题中的 EDIT 部分以获取解决方案。
编辑: 在此处发布更新的代码作为答案。问题在于我使用枚举的方式。底线是,当您需要立即获得一致的结果时,永远不要相信延迟加载。
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);
}
在 Entity Framework Core using Code First 中,我通过做两件事让它工作:
- 我将
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
装饰器添加到实体的主键,如 Yashveer Singh 的回答所述
- 我将新实体对象的主键设置为 0
执行这两个步骤后,我不需要将 IEnum 转换为数组。我只是能够 运行:
_dbContext.Entities.AddRange(entities);
await _dbContext.SaveChangesAsync();
我不知道这是 Entity Framework 的设计选择还是代表我的错误方法,但每当我尝试将 AddRange 实体添加到 DbSet 时,我似乎无法获得自动 -生成的 IDENTITY 字段。
[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);
}
请试试这个,它适用于 Int 类型列,需要在 long 类型上尝试。
[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; }
}
我在 EF 6 中使用数据库优先,在尝试了一段时间后,我找到了一个可能的解决方案。
首先,检查数据库中的 Table,确保将 'ID' 列定义为自增主键字段,可以使用类似
ID int IDENTITY(1,1) PRIMARY KEY,
创建您的 table 时。一些相关资料可以看here1 or here2.
或者您可以在 MSSQL IDE 中检查数据属性,例如:
其次,将'ID'列的StoreGeneratedPattern设置为Identity,你可以通过在Visual Studio,右击table和select属性中的Data Column,StoreGeneratedPattern设置在属性Window:
部分相关文章见here。
完成上述操作后,使用 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);
是什么导致了这个问题?可枚举!查看我问题中的 EDIT 部分以获取解决方案。
编辑: 在此处发布更新的代码作为答案。问题在于我使用枚举的方式。底线是,当您需要立即获得一致的结果时,永远不要相信延迟加载。
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);
}
在 Entity Framework Core using Code First 中,我通过做两件事让它工作:
- 我将
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
装饰器添加到实体的主键,如 Yashveer Singh 的回答所述 - 我将新实体对象的主键设置为 0
执行这两个步骤后,我不需要将 IEnum 转换为数组。我只是能够 运行:
_dbContext.Entities.AddRange(entities);
await _dbContext.SaveChangesAsync();