[英]Exception on index data annotations from a base class
我从ASP.net Core
开始,我正在创建我的模型。
我刚刚创建了两个:一个叫dto
,它将成为我所有数据库模型的基础,看起来像这样:
public abstract class Dto
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[Clustered]
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime LastUpdate { set; get; }
}
另一个叫做subscription
,它看起来像这样:
public class Subscription:Dto
{
public string Name { get; set; }
public decimal Price { set; get; }
public string MeliApiKey { get; set; }
public int MaxQueries { get; set; }
public int UsedQueries { get; set; }
}
我在Fluent API
上有以下配置:
modelBuilder.Entity<Dto.Dto>().Property(x => x.CreatedAt).HasDefaultValueSql("SYSUTCDATETIME()");
modelBuilder.Entity<Dto.Dto>().Property(x => x.LastUpdate).HasComputedColumnSql("SYSUTCDATETIME()");
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
foreach (var prop in entity.GetProperties())
{
var attr = prop.PropertyInfo?.GetCustomAttribute<ClusteredAttribute>(true);
if (attr != null)
{
var index = entity.AddIndex(prop);
index.IsUnique = true;
index.SqlServer().IsClustered = true;
}
}
}
我只添加了subscription
作为dbset
因为我不希望使用dto
Table Per Hierarchy继承。
当我运行add-migration时,出现以下错误:
“无法将索引{'CreatedAt'}添加到实体类型'Subscription',因为实体类型'Dto'上已存在相同属性的索引”
现在我用谷歌搜索了错误,但我没有看到任何地方如何解决这个问题。
我应该删除dto
类并将相同的属性添加到代表我的模型的每个对象吗?
由于错误状态,并且已在基类的属性上定义了索引。 检查属性是否声明与您当前正在处理的实体的类型相同,类似于:
var propertiesToProcess = entity.GetProperties()
.Where( p => entity.ClrType == p.PropertyInfo.DeclaringType );
我最后删除了这些行:
modelBuilder.Entity<Dto.Dto>().Property(x => x.CreatedAt).HasDefaultValueSql("SYSUTCDATETIME()");
modelBuilder.Entity<Dto.Dto>().Property(x => x.LastUpdate).HasComputedColumnSql("SYSUTCDATETIME()");
因为它们由于某种原因包括实体框架层次结构中的Dto类,所以创建每个层次结构继承表(仅产生一个表数据库)。
然后我重写了OnModelCreating的代码,如下所示:
foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
if (entity.ClrType.IsSubclassOf(typeof(Dto.Dto)))
{
modelBuilder.Entity(entity.ClrType)
.HasKey(nameof(Dto.Dto.Id)).ForSqlServerIsClustered(false);
modelBuilder.Entity(entity.ClrType)
.Property(nameof(Dto.Dto.CreatedAt))
.HasDefaultValueSql("SYSUTCDATETIME()");
modelBuilder.Entity(entity.ClrType)
.Property(nameof(Dto.Dto.LastUpdate))
.HasComputedColumnSql("SYSUTCDATETIME()");
foreach (var prop in entity.GetProperties())
{
var attr = prop.PropertyInfo?.GetCustomAttribute<ClusteredAttribute>(true);
if (attr != null)
{
var index = entity.AddIndex(prop);
index.IsUnique = true;
index.SqlServer().IsClustered = true;
}
}
}
}
如果if (entity.ClrType.IsSubclassOf(typeof(Dto.Dto)))
要快速丢弃ASP.net Core创建的表,那么只对从Dto继承的对象进行更改。
本规范:
modelBuilder.Entity(entity.ClrType)
.Property(nameof(Dto.Dto.CreatedAt))
.HasDefaultValueSql("SYSUTCDATETIME()");
modelBuilder.Entity(entity.ClrType)
.Property(nameof(Dto.Dto.LastUpdate))
.HasComputedColumnSql("SYSUTCDATETIME()");
告诉实体框架创建列CreateAt,当前UTC时间具有默认值,并使用for循环中实际实体的当前UTC时间更新LastUpdate列。
最后,这个代码得到了错误,因为Dto类被包含在数据库实体中,因此它为它创建索引,并且因为在下一个实体尝试创建索引时在数据库实体中包含该类会触发TPH同样,错误弹出(我们试图在同一个表中创建相同的索引,因为使用TPH我们只有一个表)。
foreach (var prop in entity.GetProperties())
{
var attr = prop.PropertyInfo?.GetCustomAttribute<ClusteredAttribute>(true);
if (attr != null)
{
var index = entity.AddIndex(prop);
index.IsUnique = true;
index.SqlServer().IsClustered = true;
}
}
但现在我们为每个实体分离了表,它只是起作用。
莫霍的答案帮助很大。
这里有其他答案帮我实现了这个目标:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.