我正在尝试为EF Migrations AddOrUpdate方法编写通用的包装器/扩展方法,但是,在设计时我收到以下错误:
这是我的代码:
public static void InsertOrUpdate(this Object item, Func<Object, Object> PrimaryKeyMember, DbContext Db, Func<DbContext, DbSet> DbSetAttribute, bool Commit = false)
{
try
{
DbSetAttribute.Invoke(Db).AddOrUpdate(PrimaryKeyMember, item);
//Commit if required
if (Commit)
Db.SaveChanges();
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
throw;
}
}
我还不熟悉泛型,但我可以推断出它与AddOrUpdate方法需要&#34;参考类型&#34;这一事实有关。我也尝试了以下内容:
public static void InsertOrUpdate<T>(this Object item, Func<Object, Object> PrimaryKeyMember, DbContext Db, Func<DbContext, DbSet<T>> DbSetAttribute, bool Commit = false)
{
try
{
DbSetAttribute.Invoke(Db).AddOrUpdate<T>(PrimaryKeyMember, item);
//Commit if required
if (Commit)
Db.SaveChanges();
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
throw;
}
}
但是,这会在设计时导致以下错误:
类型&#39; T&#39;必须是引用类型才能将其用作参数 泛型类型或方法中的TEntity blablabla.AddOrUpdate(...)。
我错过了什么?我不确定&#34;参考类型&#34;是...
我现在使用以下代码,它使用AddOrUpdate的一个覆盖:
public static void InsertOrUpdate<T>(this T item, Expression<Func<T, object>> IdentifierExpression, DbContext Db, Func<DbContext, IDbSet<T>> DbSetAttribute, bool Commit = false) where T: class
{
try
{
DbSetAttribute.Invoke(Db).AddOrUpdate(IdentifierExpression, item);
//Commit if required
if (Commit)
Db.SaveChanges();
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
throw;
}
}
答案 0 :(得分:2)
如果您尝试换行此DbSetMigrationsExtensions.AddOrUpdate
扩展名,那么我无法理解Func<Object, Object> PrimaryKeyMember
的含义。
无论如何,AddOrUpdate
被限制为使用类(==引用类型)作为实体类型。因此,您的包装器方法也必须以这种方式进行约束:
public static void InsertOrUpdate<T>(this Object item, Func<Object, Object> PrimaryKeyMember, DbContext Db, Func<DbContext, DbSet<T>> DbSetAttribute, bool Commit = false)
where T : class
{
// ...
}
<强> UPD 强>
由于您尝试使用AddOrUpdate
的{{3}}重载,您应该注意,Func<...>
和Expression<Func<...>>
是两种不同的类型。第一个是委托,第二个是代码的树状表示,可以编译成具有特定签名的委托。
您必须将PrimaryKeyMember
参数类型从Func<T, object>
更改为Expression<Func<T, object>>
。