我有一个没有键的表,将 Id 作为唯一不可为空的列,我必须写入它,因此我必须在代码中定义键,选择可能用作键的列。
[Table("AvailableProducts")]
public class AvailableProducts
{
public int Id { get; set; }
public string? A { get; set; }
public string? B { get; set; }
public string? C { get; set; }
}
Id、A、B 列都可以是组合键。
根据我的背景设置:
modelBuilder.Entity<AvailableProducts>().HasKey(u => new
{
u.Id,
u.A,
u.B
});
调用 context.SaveChanges() 没有问题;数据被插入到我的表中。
问题出在尝试读取数据时。调用 context.ToListAsyc();
我收到错误: 数据为空。无法对 Null 值调用此方法或属性。
如果我设置 modelBuilder.Entity().HasNoKey(); 我没有收到错误并获取我需要的数据,但我无法不再保存数据,因为 EF 确实需要密钥来写入。
我尝试将属性更改为 [Key]、[Required] 并从 string? 更改为 string 但似乎不起作用,我可以保存或读取,但不能同时保存和读取。
您的情况是实体框架 (EF) 中的一个不寻常的场景,因为 EF 是围绕拥有键的实体的想法而设计的。由于各种原因,包括潜在的数据不一致,通常不建议使用没有唯一键的表。
但是,针对你现在的情况:
您可以将模型分开进行读取和写入。
阅读模型:
[Table("AvailableProducts")]
public class AvailableProductsRead
{
public int Id { get; set; }
public string? A { get; set; }
public string? B { get; set; }
public string? C { get; set; }
}
写作模型:
public class AvailableProductsWrite
{
public int Id { get; set; }
public string A { get; set; }
public string B { get; set; }
public string? C { get; set; }
}
您需要调整 DbContext 中的模型配置。
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// For writing
modelBuilder.Entity<AvailableProductsWrite>()
.ToTable("AvailableProducts")
.HasKey(u => new
{
u.Id,
u.A,
u.B
});
// For reading
modelBuilder.Entity<AvailableProductsRead>()
.HasNoKey()
.ToView("AvailableProducts");
}
以下是使用这两种模型的方法:
写入(插入新记录):
var newProduct = new AvailableProductsWrite { Id = 1, A = "valueA", B = "valueB", C = "valueC" };
context.Add(newProduct);
await context.SaveChangesAsync();
阅读:
var products = await context.Set<AvailableProductsRead>().ToListAsync();
此解决方案旨在解决您遇到的限制。如果可以的话,请考虑重构您的数据库架构,以在将来包含正确的主键和唯一键。