EF Core 处理备用主键
EF Core dealing with alternate primary keys
我有一些 EF Core 模型是使用 dotnet ef dbContext scaffold
构建的,以使用数据库优先方法生成模型。我的问题是数据库使用整数主键,用于将 table 链接在一起,但有一个基于字符串的索引,可用作搜索 table.
的合理索引
但是:当我尝试使用 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'.
那么,两个问题:
- EF 如何确定主键是什么?
- 有什么方法可以重新调整它以便我可以使用 "Find" 按名称搜索实体,但保留自动增量主键?
- 我喜欢自动递增整数键作为加入 table 的字段是不是很愚蠢?
它们看起来像这样:
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);
}
创建 table 的 SQL 看起来像:
CREATE TABLE [tb_entity]
(
_id BIGINT PRIMARY KEY IDENTITY(1,1),
key NVARCHAR(255) CONSTRAINT uq_entity_key UNIQUE NOT NULL,
);
- How did EF Figure out what the primary key was?
如果未通过 [Key]
属性或 HasKey
流畅 API 明确指定,则由 convention:
By convention, a property named Id
or <type name>Id
will be configured as the key of an entity.
您可以通过检查
看到该信息
var pk = context.Model.FindEntityType(typeof(Entity)).FindPrimaryKey();
- Is there any way I can re-jig this so I can use "Find" to search for entities by name, but keep the autoincrement primary keys?
你可以在EF Core using data annotations/fluent API说Entity
的PK是Name
,但我不建议这样做,因为那样会导致错误FK 关系的假设,一般来说是不好的。
相反,不要使用专用于 PK 的 Find
/ FindAsync
方法。 First
、FirstOrDefault
、Single
和 SingleOrDefault
(以及对应的 Async
)允许您按任何条件进行搜索,例如而不是 FindAsync("abc000")
你会使用 FirstOrDefaultAsync(e => e.Name == "abc000")
.
唯一不同的是Find
方法先在本地缓存中查找,这在大多数使用场景下并没有太大的好处。另一方面,Find
方法不支持预先加载,而后者支持。后者是针对数据库执行的,并且由于该列上有唯一索引,因此它们应该具有足够的性能。
- Am I being stupid for preferring auto increment integer keys as the fields to join tables on?
这是非常标准的数据库设计,通常优于自然 PK,我认为这没有任何问题。
我有一些 EF Core 模型是使用 dotnet ef dbContext scaffold
构建的,以使用数据库优先方法生成模型。我的问题是数据库使用整数主键,用于将 table 链接在一起,但有一个基于字符串的索引,可用作搜索 table.
但是:当我尝试使用 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'.
那么,两个问题:
- EF 如何确定主键是什么?
- 有什么方法可以重新调整它以便我可以使用 "Find" 按名称搜索实体,但保留自动增量主键?
- 我喜欢自动递增整数键作为加入 table 的字段是不是很愚蠢?
它们看起来像这样:
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);
}
创建 table 的 SQL 看起来像:
CREATE TABLE [tb_entity]
(
_id BIGINT PRIMARY KEY IDENTITY(1,1),
key NVARCHAR(255) CONSTRAINT uq_entity_key UNIQUE NOT NULL,
);
- How did EF Figure out what the primary key was?
如果未通过 [Key]
属性或 HasKey
流畅 API 明确指定,则由 convention:
By convention, a property named
Id
or<type name>Id
will be configured as the key of an entity.
您可以通过检查
看到该信息var pk = context.Model.FindEntityType(typeof(Entity)).FindPrimaryKey();
- Is there any way I can re-jig this so I can use "Find" to search for entities by name, but keep the autoincrement primary keys?
你可以在EF Core using data annotations/fluent API说Entity
的PK是Name
,但我不建议这样做,因为那样会导致错误FK 关系的假设,一般来说是不好的。
相反,不要使用专用于 PK 的 Find
/ FindAsync
方法。 First
、FirstOrDefault
、Single
和 SingleOrDefault
(以及对应的 Async
)允许您按任何条件进行搜索,例如而不是 FindAsync("abc000")
你会使用 FirstOrDefaultAsync(e => e.Name == "abc000")
.
唯一不同的是Find
方法先在本地缓存中查找,这在大多数使用场景下并没有太大的好处。另一方面,Find
方法不支持预先加载,而后者支持。后者是针对数据库执行的,并且由于该列上有唯一索引,因此它们应该具有足够的性能。
- Am I being stupid for preferring auto increment integer keys as the fields to join tables on?
这是非常标准的数据库设计,通常优于自然 PK,我认为这没有任何问题。