我有一些使用dotnet ef dbContext scaffold
构建的EF Core模型,使用数据库第一种方法生成模型。我的问题是数据库使用整数主键,用于将表链接在一起,但有一个基于字符串的索引,可用作搜索表的理智索引。
但是:当我尝试使用FindAsync("abc000")
时,我得到一个完全预期的错误The key value at position 0 of the call to 'DbSet<Entity>.Find' was of type 'string', which does not match the property type of 'long'.
那么,有两个问题:
它们看起来像这样:
class Entity
{
long Id;
string Key;
};
在OnModelCreating中:
modelBuilder.Entity<Entity>(entity =>
{
entity.ToTable("tb_entity", "main");
entity.HasIndex(e => e.Key)
.HasName("uq_entity_key")
.IsUnique();
entity.Property(e => e.Id).HasColumnName("_id");
entity.Property(e => e.Key)
.HasColumnName("key")
.HasMaxLength(255);
}
创建表的SQL如下所示:
CREATE TABLE [tb_entity]
(
_id BIGINT PRIMARY KEY IDENTITY(1,1),
key NVARCHAR(255) CONSTRAINT uq_entity_key UNIQUE NOT NULL,
);
- EF如何确定主键是什么?
如果没有通过[Key]
属性或HasKey
流畅API明确指定,则由convention:
按照惯例,名为
Id
或<type name>Id
的属性将被配置为实体的键。
您可以通过检查来查看该信息
var pk = context.Model.FindEntityType(typeof(Entity)).FindPrimaryKey();
- 有什么方法可以重新设置这个,所以我可以使用“查找”按名称搜索实体,但保留自动增量主键?
你可以使用Entity
的PK为Name
的数据注释/流畅的API来说谎EF Core,但我不建议这样做,因为这将导致对FK关系的错误假设,并且通常是坏的。
相反,只是不要使用专用于PK的Find
/ FindAsync
方法。 First
,FirstOrDefault
,Single
和SingleOrDefault
(以及他们的Async
对应物)允许您按任何标准搜索,例如而不是FindAsync("abc000")
你会使用FirstOrDefaultAsync(e => e.Name == "abc000")
。
唯一的区别是Find
方法首先在本地缓存中搜索,这在大多数使用场景中没有太大的好处。从另一方面来说,Find
方法不支持急切加载,而后者则支持。后者是针对数据库执行的,由于该列上有唯一索引,因此它们应该具有足够的性能。
- 我更喜欢将自动增量整数键作为连接表的字段而愚蠢吗?
这是非常标准的数据库设计,通常比自然PK更好,我没有看到任何问题。