【发布时间】:2021-03-20 04:28:33
【问题描述】:
我有一个抽象基类,它是所有派生(~100)类的基础。 这个基类应该不保存到数据库中,但它的属性应该作为派生类中的列公开 -> 实体模型。 在 Db 上下文代码(OnModel Creation 等)中,没有提及 BaseEntity - 仅提及其派生类。
在 3.0.1 中,这很好用。 BaseEntity 被忽略,仅提及的类(通过 DbSet 或 OnModelxxx 中)被配置为 TPH。
System.InvalidOperationException:无法为“BaseEntity”创建 DbSet,因为该类型未包含在上下文模型中。
如何恢复以前的行为?
我的基类:
public abstract class BaseEntity
{
[Key]
[GraphQLName("id")]
[GraphQLNonNullType(IsNullable = true)]
public Guid Identifier { get; set; } = Guid.NewGuid();
[GraphQLNonNullType(IsNullable = true)]
public DateTime CreatedDate { get; set; } = DateTime.UtcNow;
[GraphQLNonNullType(IsNullable = true)]
public DateTime LastModifiedDate { get; set; } = DateTime.UtcNow;
[GraphQLNonNullType(IsNullable = true)]
public DateTime DisplayDate { get; set; } = DateTime.UtcNow;
public string DisplayName { get; set; } = string.Empty;
public string DisplayText { get; set; } = string.Empty;
public string DisplayDescription { get; set; } = string.Empty;
public string TypeName { get; set; }
}
.....
派生类示例:
public class Document : BaseEntity
{
[GraphQLIgnore]
public Organization Organization { get; set; }
[GraphQLNonNullType(IsNullable = true)]
public DocumentType DocumentType { get; set; }
/// <summary>
/// Mimetype of the document
/// </summary>
[GraphQLName("type")]
[GraphQLNonNullType(IsNullable = true)]
public string MimeType { get; set; }
}
保存代码 - 使用 BaseEntity - 在 SaveChangesAsync() 上引发异常
public async Task<List<T>> Upsert<T>(List<T> baseEntities, bool isRaiseBaseEntityChangeEvent = true) where T : class
{
var entities = new HashSet<BaseEntity>();
foreach (var b in baseEntities)
{
entities.Add(b as BaseEntity);
TraverseGraph(b as BaseEntity, ref entities);
}
using (var context = GetDbInstance())
{
try
{
foreach (var e in entities)
{
//exists in db
if (e.IsPersistedToDatabase == true)
{
context.Attach(e);
foreach (var entry in context.Entry(e).Properties)
{
try
{
if (entry.Metadata.Name.Equals("CreatedDate"))
{
// Don't allow changing the CreatedDate on existing objects.
entry.IsModified = false;
}
else if (entry.CurrentValue != null && !entry.Metadata.IsPrimaryKey())
{
entry.IsModified = true;
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
continue;
}
}
}
else
{
e.IsPersistedToDatabase = true;
context.Set<BaseEntity>().Add(e);
}
}
//make a copy for the change event
List<BaseEntityEntry> baseEntries = new List<BaseEntityEntry>();
foreach (var e in context.ChangeTracker.Entries())
baseEntries.Add(new BaseEntityEntry()
{
Entity = e.Entity as BaseEntity,
State = e.State
});
await context.SaveChangesAsync();
#region BaseEntity change event raising
if (isRaiseBaseEntityChangeEvent)
{
EventsPublisher.Instance.SignalEntityChange(new BaseEntityChangeEventArgs()
{
Entities = baseEntries
});
}
#endregion
return baseEntities;
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
throw ex;
}
}
}
【问题讨论】:
-
显示产生异常的代码。
-
这有点特殊 - 关键是在保存期间所有派生类都被引用为基本抽象类:
codepublic async Task- > Upsert
(List baseEntities, bool isRaiseBaseEntityChangeEvent = true) where T : class code -
我怀疑这段代码在以前的 EFC 版本中是否有效,但这并不重要,因为
Set<BaseEntity>()不是正确的调用。将context.Set<BaseEntity>().Add(e);替换为context.Add(e);。 -
@ChrisCardinal Ivan Stoev 是正确的.....
-
我刚刚添加了一个 Q/A 来解决这个问题。见stackoverflow.com/questions/65778874/…