泛型方法是否可以返回我指定的属性
本文关键字:属性 返回 是否 泛型方法 | 更新日期: 2023-09-27 18:00:53
昨天Ognyan帮我写了很多方法:
public static class DbSetExtensions
{
public static T AddIfNotExists<T>(this DbSet<T> dbSet, T entity, Expression<Func<T, bool>> predicate = null) where T : class, new()
{
var exists = predicate != null ? dbSet.Any(predicate) : dbSet.Any();
return !exists ? dbSet.Add(entity) : null;
}
}
当这对我的实体进行Add时,我会返回实体的新ID,但如果它存在,则返回null。
有时我想取回已经存在的实体的ID。但是,我的实体的Key ID属性将根据模型的不同而有所不同。例如,Address模型的键是AddressId,Profile的键是ProfileId。
因此,我想修改这个查询(或制作它的另一个版本(,以接受Id属性名称作为参数。(或者使用EF来识别主键。(然后做这样的事情:
public static class DbSetExtensions
{
public static T AddIfNotExists<T>(this DbSet<T> dbSet,
T entity,
Expression<Func<T, bool>> predicate = null,
Expression<Func<T, TId>> keyColumnName) where T : class, new()
{
var exists = predicate != null ? dbSet.Where(predicate).Select(e => e.keyColumnName) : dbSet.Any();
return !exists ? dbSet.Add(entity) : exists ;
}
}
我不确定这是否是定义我想要使用的属性的正确方式。我也意识到这可能没有只做Any((那么快,但有时我们可能需要获得ID。
我也想更好地理解所有这些项目的含义以及它们是如何协同工作的。我到处都是,弄得零零星星,但还没能把整个谜题拼在一起。
也许有更好的解决方案,但你可以尝试一下:
public static TResult AddIfNotExists<T,TResult>(this DbSet<T> dbSet,
T entity,
Expression<Func<T, bool>> predicate,
Expression<Func<T, TResult>> columns
) where T : class, new()
{
if (predicate==null || columns==null)
throw new Exception();
//Find if already exist the entity and select its key column(s)
var result = dbSet.Where(predicate).Select(columns).FirstOrDefault();
//the result could be a reference type (string or anonymous type) or a value type
if (result!=null && !result.Equals(default(TResult)))
return result;
var newElement = dbSet.Add(entity);
//Compile the Expresion to get the Func
var func = columns.Compile();
//To select the new element key(s), add the element to an array (or List) to apply the Select method and get the keys
var r = new[]{newElement};
return r.Select(func).FirstOrDefault();
}
正如你所看到的,我总是希望参数predicate
检查元素是否已经存在,columns
选择键,以防你有一个具有复合PK的实体(但请注意,你可以从该实体中选择你想要的所有属性,而不仅仅是键(。然后,我应用表达式进行筛选,并在元素存在的情况下选择键。如果它不存在,我会将实体添加到它的DbSet<T>
中,但存在问题。如何获取新元素密钥?好吧,我找到的唯一解决方案是将该元素添加到数组中,编译表达式以获得Func<T,TResult>
,并将该Func<T,TResult>
应用于数组,(我知道这可能不是最好的解决方案,但它应该有效(。
例如,要为具有复合PK的实体调用此扩展方法,可以执行以下操作:
.AddIfNotExists(element, e => e.UserName== "admin", e => new{ e.Id1,e.Id2});
您的情况应该更简单:
public static class DbSetExtensions
{
public static T AddIfNotExists<T>(this DbSet<T> dbSet, T entity,
Expression<Func<T, bool>> predicate = null) where T : class, new()
{
T exists = predicate != null ?
dbSet.Where(predicate).FirstOrDefault():
dbSet.FirstOrDefault();
return exists == null ?
dbSet.Add(entity):
exists;
}
}
然后,正如您似乎知道PK属性一样,您可以从返回的值中检查它。