我从不想删除某些表中的行,所以我添加了一个IsDeleted列。
代表这些表的POCS都实现了IDeleteable接口。
当我做类似的事情时 -
foreach (ITransactionItem transactionItem in Transaction.TransactionItemCollection.AsEnumerable().ToList())
{
ITransactionItem transactionItemModel = new TransactionItemModel();
transactionItemModel.CopyFrom(transactionItem);
transactionItem.PickUpQuantity = 0;
transactionItem.IsPickUp = false;
this.PickUpItemCollection.Add(transactionItemModel);
}
我想回到没有设置IsDeleted位的行。
我不想将context.Users.Where(u => u.Firstname == "Dave")
添加到&& IsDeleted == false
我还希望此解决方案适用于Where
,Single
或First
等
我想要解决这个问题question。
答案 0 :(得分:2)
根据下面的trailmax评论,是的,下面的原始答案确实将所有数据加载到内存中,因为它暴露了链式枚举。
尝试将IQueryable
个调用链接在一起时会出现两个问题。
.Invoke()
来电.Where()
之类的命名约定,则最终会选择错误的扩展名,因为IDeletable
只会公开一个可以构建谓词的列。以下内容依赖于LinqKit库来链表达式,语法不再流畅,但它确实避免了立即执行。
var users = context.Users.WhereIsNotDeleted(x => x.Id > 0).ToList();
public static class Extension
{
public static IEnumerable<T> WhereIsNotDeleted<T>(this IQueryable<T> source,
Expression<Func<T, bool>> predicate) where T : IDeletable
{
var query = source.AsExpandable().Where(x => !x.IsDeleted);
return query.Where(predicate);
}
}
假设IDeletable
保证存在IsDeleted
,您可以创建一个始终为您执行此检查的扩展方法。
public interface IDeletable
{
bool IsDeleted { get; set; }
}
public static class Extension
{
public static IEnumerable<T> WhereNotDeleted<T>(this IEnumerable<T> source,
Func<T, bool> predicate) where T : IDeletable
{
return source.Where(x => !x.IsDeleted).Where(predicate);
}
}
在下面的简单测试中,只返回了两条记录,因为第三条记录已被软删除。
void Main()
{
var x = new List<Test>();
x.Add(new Test{ Number = "one" });
x.Add(new Test{ Number = "two" });
x.Add(new Test{ Number = "three", IsDeleted = true });
var y = x.WhereNotDeleted(a => a != null);
y.Count().Dump();
}
public class Test : IDeletable
{
public string Number { get; set; }
public bool IsDeleted { get; set; }
}
根据您的评论,如果您希望它与EXISTING LINQ扩展方法一起使用,您实际上无法实现,因为您遇到了调用歧义。
如果您想调用.Where()
并将其转换为您的条件仅适用于实现IDeletable
的对象,则需要包装每个LINQ扩展方法。
public static class Extension
{
public static IEnumerable<IDeletable> Where(this IEnumerable<IDeletable> source,
Func<IDeletable, bool> predicate)
{
return System.Linq.Enumerable.Where(source, (x => predicate(x) && !x.IsDeleted));
}
}
在这些扩展方法中,您必须通过实例调用而不是作为扩展方法调用基本LINQ方法,否则您将遇到堆栈溢出异常。
答案 1 :(得分:0)
您可以为每个具有where子句作为其过滤器的表创建一个视图。然后,您可以从实体框架而不是基础表访问该视图,而不用担心它。您的用户永远不会知道基础表,只知道视图。