我在使用 EF Core 3.1 时遇到了问题。 使用直到最近才运行的代码。我有在 DbContext 上调用 SaveChanges 之前调用的此方法:
private void SetProps<TEntity>(TEntity dbEntity, EntityState newState)
where TEntity : class, new()
{
var entry = this.dbContext.Entry(dbEntity);
...
if (dbEntity is IDbEntityBase dbEntityBase)
{
var baseEntry = this.dbContext.Entry(dbEntityBase);
if (newState == EntityState.Added)
{
baseEntry.Property(t => t.Id).CurrentValue = Guid.NewGuid();
}
}
}
为了便于阅读,省略了大量代码,因此很难进行任何设计更改。
我遇到的问题在于打电话给baseEntry.Property(t => t.Id).CurrentValue = Guid.NewGuid();
.调用该代码时,EF 将引发异常'this' type cannot be an interface itself.
。
IDbEntity 是所有实体类实现的一些基本接口(它具有一些通用属性(。
EF 调用堆栈如下所示:
System.ArgumentException: 'this' type cannot be an interface itself.
at System.RuntimeTypeHandle.VerifyInterfaceIsImplemented(RuntimeTypeHandle interfaceHandle)
at System.RuntimeType.GetInterfaceMap(Type ifaceType)
at System.Reflection.RuntimeReflectionExtensions.GetRuntimeInterfaceMap(TypeInfo typeInfo, Type interfaceType)
at Microsoft.EntityFrameworkCore.Infrastructure.ExpressionExtensions.GetPropertyAccess(LambdaExpression propertyAccessExpression)
at Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry`1.Property[TProperty](Expression`1 propertyExpression)
at InDocEdge.Sap.Database.EfContext.SapDbContext.ProcessBeforeSaveChangesData() in C:MyCodeMyDbContext.cs:line 2
at InDocEdge.Sap.Database.EfContext.SapDbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) in C:MyCodeMyDbContext.cs:line 1
代码直到最近才工作,但不知何故,现在 EF 不满意(据我所知(我为 Entry 方法提供接口类型,我认为这是可能的。
有谁知道可能出了什么问题或如何解决这个问题?
接口类型没有实体条目这样的东西。 它必须是实体类型。EntityEntry<TEntity>.Property
需要找到实体类型属性,而不是接口属性(它们在概念上和实际上可能不同(。
但在正常情况下,您的实体属性实现IDbEntityBase.Id
也将被称为Id
,您只需将该名称传递给entry.Property(string)
,例如:
private void SetProps<TEntity>(TEntity dbEntity, EntityState newState) where TEntity : class, new()
{
var entry = Entry(dbEntity);
if (dbEntity is IDbEntityBase)
{
if (newState == EntityState.Added)
{
entry.Property(nameof(IDbEntityBase.Id)).CurrentValue = Guid.NewGuid();
}
}
}
或者,由于您只是设置EntityEntry.CurrentValue
,因此可以直接通过 Entity 对象、IDbEntityBase 引用而不是 EntityEntry 来设置它。 例如:
private void SetProps<TEntity>(TEntity dbEntity, EntityState newState) where TEntity : class, new()
{
if (dbEntity is IDbEntityBase dbEntityBase)
{
if (newState == EntityState.Added)
{
dbEntityBase.Id = Guid.NewGuid();
}
}
}