[英]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.