c# - EF 核心实体 ID 作为具有标识列的自定义类
问题描述
我想在我的实体模型中使用强类型 ID,映射到DB 中的自动递增int(例如 MS SQL Identity 列)。但 EF Core 3.1 不支持自定义类型的标识:
public class Vendor
{
public VendorId Id { get; private set; }
public string CompanyName { get; set; }
}
public class VendorId
{
public int Value { get; }
public VendorId(int value)
{
Value = value;
}
}
public void Configure(EntityTypeBuilder<Vendor> vendorEntity)
{
vendorEntity.HasKey(vendor => vendor.Id);
vendorEntity.Property(vendor => vendor.Id)
.HasConversion(vendorId => vendorId.Value, dbValue => new VendorId(dbValue))
.UseIdentityColumn();
}
有了这个模型,我得到了例外:
标识值生成不能用于实体类型“供应商”上的属性“Id”,因为该属性类型是“供应商Id”。标识值生成只能与有符号整数属性一起使用。
我还尝试映射到私有整数支持字段int id
,但是我不能在 EF 查询中使用 Id 属性。所以它看起来不是一个解决方案。
类似的问题是当我尝试 HiLo 密钥生成时。
您对如何解决这个问题有任何想法吗?
解决方案
我使用 c# 9 记录使用的解决方案(在 ef core 5 中):
public abstract record StronglyTypedId<TValue>(TValue Value) where TValue : notnull
{
public override string ToString() => Value.ToString();
}
使用抽象实体模型:
public abstract class Entity<TId, T> where TId: StronglyTypedId<T>
{
T _Id;
public virtual TId Id
{
get { return (TId)Activator.CreateInstance(typeof(TId), new object[] {_Id}); }
}
}
然后是一个示例实体模型
using TId = Int32;
public record EntityTypeId(TId Value) : StronglyTypedId<TId>(Value);
public class EntityName<EntityTypeId, TId>
{
private EntityName() {} //for ef core
}
然后在模型构建器中(可以再次成为抽象/基础模型构建器)
builder.Ignore(e => e.Id);
builder
.Property("_Id")
.HasColumnName("Id")
.UseIdentityColumn();
builder.HasKey("_Id");
这确实意味着从数据库(通过命令或存储库)检索时,您需要使用名称,例如
public async Task<EntityName> GetEntity(EntityTypeId typedId)
{
var entity = await context.EntityName
.FirstOrDefaultAsync(x => EF.Property<int>(x, "_Id") == typedId.Value);
return entity;
}
不完美但有效
推荐阅读
- android - 如何在 Kotlin (Android Studio) 中获取 http 请求
- regex - 正则表达式 - 从重复字符串中删除部分文本
- javascript - 只有当用户来自某个页面/站点时,有没有办法显示文本或对话?
- python - Literal eval of Python object from command-line arg
- generics - 如何在 kotlin 中扩展函数类型?
- python - 如何在 Python 编写的聊天机器人中插入计算器
- docker - Traefik 基本认证
- c# - 允许 IdentityServer 客户端的一切?
- python - 用 Python 从 PDF 文件中读取内容
- python - 阻塞 = False 的调度程序