0

我有一个地址列表,而地址定义如下:

public class Address
{
    public int Id { get; set; }
    public string Name { get; set; }
    public DateTime ModifiedDate { get; set; }
}

根据之前的调用,我有一个元组列表,而一个元组由地址 id 和修改日期组成。

e.g. List<Tuple<int, DateTime>>

现在我想获取所有具有相应 id 的地址,但前提是它们已被修改。

我已将元组列表转换为包含 id 和字典的 int 数组,而 id 是键,修改日期是值。

int[] ids;
Dictionary<int, DateTime> dates;

以下足以获取具有相应id的所有地址。

addressList.Where(a => ids.Contains(a.Id));

不幸的是,以下是不可能的:

例外:“LINQ to Entities 无法识别方法 'System.DateTime get_Item(Int32)' 方法,并且此方法无法转换为存储表达式。”

addressList.Where(a => ids.Contains(a.Id) && dates[a.Id] < a.ModifiedDate);

这个问题可以通过一个循环来解决,但我正在寻找一个更优雅的解决方案。

List<Address> modifiedAddressList = new List<Address>();
foreach (Address a in addressList)
{
    if (a.ModifiedDate > dates[a.Id]) modifiedAddressList.Add(a);
}
4

2 回答 2

2

这里的问题是 LinqToEntities 不了解您的字典 - 以及如何将其转换为数据库查询。

你有几个选择:

  1. 循环遍历每个项目(如您所建议的)
  2. 传入修改记录的ID
  3. 将整个数据集下载到客户端(使用 ToList()),然后使用您的字典方法

选项 #3 非常简单——如果您不处理大型数据集:

addressList
    .Where(a => ids.Contains(a.Id))
    .AsEnumerable()
    .Where(dates[a.Id] < a.ModifiedDate);
于 2013-09-20T15:06:48.037 回答
2

目前,您的应用程序中有一本包含一些信息的字典,以及数据库中的一些当前日期。您需要将两者放在同一个地方才能比较两个数据集。这意味着要么将字典中的信息传递到数据库,要么在进行比较之前将数据从数据库返回到应用程序。

如果要将数据发送到数据库,则需要通过 SQL 完成;您的数据库不能只运行任何旧的 C# 代码,这似乎是您正在尝试做的事情以及为什么它不起作用。

“更简单”的解决方案可能是做您似乎不太喜欢的事情,即从数据库中提取数据,然后在您的应用程序中对其进行过滤。另一种选择是将字典中的数据上传到临时表,然后将两个表连接在一起。

如果您愿意,可以使用更多 LINQ-esk 方式执行第一个选项:

addressList.Where(a => ids.Contains(a.Id))
    .AsEnumerable()
    .Where(a => dates[a.Id] < a.ModifiedDate);

AsEnumerable调用将确保在您的应用程序中执行后续方法,而不是转换为 SQL。Contains检查可以翻译成 SQL 中的 IN 子句,所以它应该在调用之前AsEnumerable所以它在 DB 端完成。

于 2013-09-20T15:09:01.500 回答