我的搜索/群组功能出现问题。
上下文
我有一个客户对象列表(实体框架上下文),我想在此列表中找到所有可能的重复项。如果对象是重复的标准应该是动态的。让我们说可以通过UI选择。
模型
让我们假设以下部分。
我的CustomerClass
public class Customer
{
public int CustomerId { get; set; }
public string SearchName { get; set; }
public string Mail { get; set; }
public DateTime? Birthday { get; set; }
public string CardNumber { get; set; }
public DateTime Created { get; set; }
}
重复的可能标准是:SearchName,Mail,Birthday和CardNumber。
以下函数返回适当的结果:
public IList<Customer> GetPossibleDuplicates()
{
IList<Customer> list;
list =
(from s in this.Context.Customers
group s by new
{
s.SearchName,
s.CardNumber
}
into g where g.Count() > 1 select g)
.SelectMany(g => g)
.OrderBy(o => o.SearchName)
.ThenBy(c => c.Created)
.ToList();
return list;
}
我遇到的问题是按照声明制作小组&#34;动态&#34;所以根据选定的creteria进行分组。有什么好的解决方案的建议吗?
答案 0 :(得分:0)
Enumerable.GroupBy允许IEqualityComparer的参数。请参阅the MSDN page。
此比较器可能是查询的动态部分。您声明分组基于选择标准,因此这将为您提供:
public IList<Customer> GetPossibleDuplicates()
{
var comparer = SomeMethodReturningAnEqualityComparerBasedOnSelectionCriteria();
return this.Context.Customers
.GroupBy(customer => customer, comparer)
.SelectMany(g => g)
.OrderBy(o => o.SearchName)
.ThenBy(c => c.Created)
.ToList();
}
返回比较器的方法将返回IEqualityComparer<Customer>
。
答案 1 :(得分:0)
如何依赖围绕IComparable
构建的标准Func<Customer, IComparable> criteria
并且封装在方法中的查询看起来像这样
public IList<Customer> FindByCriteria(Func<Customer, IComparable> criteria)
{
var query = from customer in FindAll()
group customer by criteria(customer)
into groups
where groups.Count() > 1
from item in groups
orderby item.SearchName, item.Created
select item;
return query.ToList();
}
然后,您可以使用自己的数据结构,甚至使用Tuple
void Main()
{
var repository = new Repository();
//Find all
repository.FindAll().Dump();
// Find by mail
var mail = new Func<Customer, IComparable>(customer =>
{
return Tuple.Create(customer.Mail);
});
repository
.FindByCriteria(mail)
.Dump();
// Find by mail and card number
var multi = new Func<Customer, IComparable>(customer =>
{
return Tuple.Create(customer.CardNumber, customer.Mail);
});
repository
.FindByCriteria(multi)
.Dump();
}
完整的存储库代码如下所示
public class Repository
{
public IList<Customer> FindByCriteria(Func<Customer, IComparable> criteria)
{
var query = from customer in FindAll()
group customer by criteria(customer)
into groupings
where groupings.Count() > 1
from grouping in groupings
orderby grouping.SearchName, grouping.Created
select grouping;
return query.ToList();
}
public IEnumerable<Customer> FindAll()
{
yield return new Customer
{
CustomerId = 1,
SearchName = "John",
CardNumber = "0000 0000 0000 0000 1",
Mail = "john.doe@test.com",
};
yield return new Customer
{
CustomerId = 2,
SearchName = "Jim",
CardNumber = "0000 0000 0000 0000 2",
Mail = "jim.doe@test.com",
};
yield return new Customer
{
CustomerId = 3,
SearchName = "Jack",
CardNumber = "0000 0000 0000 0000 3",
Mail = "jack.doe@test.com",
};
yield return new Customer
{
CustomerId = 4,
SearchName = "Jane",
CardNumber = "0000 0000 0000 0000 3",
Mail = "john.doe@test.com",
};
yield return new Customer
{
CustomerId = 4,
SearchName = "Joan",
CardNumber = "0000 0000 0000 0000 3",
Mail = "john.doe@test.com",
};
}
}
答案 2 :(得分:-1)
您的查询可以重写为:
var result = this.Context.Customers
.GroupBy(x => new { x.SearchName, x.CardNumber })
.Where(x => x.Count() > 1)
.SelectMany(x => x)
.OrderBy(x => x.SearchName)
.ThenBy(x => x.Created)
.ToList();
您可以看到.GroupBy(...)
调用采用Expression<Func<Customer, TKey>>
类型的表达式,其中TKey
是匿名类型。因此,如果您可以设法动态生成表达式,那么您可以解决问题。
我必须承认匿名类型是由编译器创建的,因此您的C#代码中还没有该类型。