使用LINQ to Entities进行数据绑定时重复行

时间:2009-06-16 14:27:02

标签: .net asp.net linq

我在将telerik RadGrid和普通的ASP.NET GridView绑定到以下LINQ to实体查询的结果时遇到问题。在这两种情况下,网格都包含正确的行数,但只有少数几行的数据在所有其他行中都是重复的。我直接从此代码中将返回值分配给网格上的DataSource属性。

public IEnumerable<DirectoryPersonEntry> FindPersons(string searchTerm)
{
    DirectoryEntities dents = new DirectoryEntities();
    return from dp in dents.DirectoryPersonEntrySet
           where dp.LastName.StartsWith(searchTerm) || dp.Extension.StartsWith(searchTerm)
           orderby dp.LastName, dp.Extension
           select dp;
}

ADDED:这是可行的备用普通ADO.NET代码:

    DataTable ret = new DataTable();
    using (SqlConnection sqn = new SqlConnection(ConfigurationManager.ConnectionStrings["WaveAdo"].ConnectionString))
    {
        SqlDataAdapter adap = new SqlDataAdapter("select * from DirectoryPersonList where LastName like '" + searchTerm + "%' order by LastName ", sqn);
        sqn.Open();
        adap.Fill(ret);
    }
    return ret;

更多

  1. LINQ发送给SQL Server的查询有效。
  2. 在返回LINQ查询结果之前迭代它们会产生相同的重复。
  3. 在绑定之前迭代LINQ结果调用方法会导致相同的重复。
  4. 更新: 基于下面 Marc Gravel 的非常合理和合适的建议,我发现EF设计师对我的实体类的实体键做了一个非常没有受过教育的猜测,这是其字段列表中的第一个字段,部门,其中只有大约七个条目在所有其他记录中共享。

    这确实是重复的原因。如果我只能更改或删除实体密钥,但这个EF设计师具有Etch-a-Sketch的所有业务逻辑,令人钦佩地承诺重复它的密钥选择,同时嘲笑我锁在外面乞求改变密钥。 / p>

4 个答案:

答案 0 :(得分:30)

在我看来,你有一个borked主键。 LINQ-to-SQL和EF的“身份管理”方面意味着只要它看到相同对象类型的相同主键值,就必须返回相同的实例。

例如,给定数据:

id     | name       | ...
-------+------------+------
1      | Fred       | ...
2      | Barney     | ...
1      | Wilma      | ...
1      | Betty      | ...

然后如果它认为id是主键,当从LINQ迭代对象时,强制给你“Fred”,“Barney “,”弗雷德“,”弗雷德“。本质上,当它再次看到id 1时,它甚至不会查看其他列 - 它只是从身份缓存中获取id 1的实例 - 并为您提供相同的Fred实例你以前。如果认为id是主键,它会将每一行视为一个单独的对象(如果它在其中一个字段中具有与另一个记录相同的值,那该怎么办? - 这并不完全不寻常。)

我建议检查您标记为主键的任何字段(在DBML / EDM模型中)确实每行都是唯一的。在上面的情况中,id列显然不代表唯一标识符,因此不适合作为主键。只需在LINQ-to-SQL / EF设计器中取消标记即可。


更新:特别是,请查看设计器中各种属性的“实体键”属性 - 尤其是在查询视图时。检查“实体密钥”是否仅对于合适的列(即使该行唯一的列)设置为true。如果设置不正确,请将其设置为false。这也可以看作黄色钥匙图标 - 这应该只出现在真正是记录的唯一标识符的东西上。

答案 1 :(得分:1)

如果您将链接查询包装在括号中并使用.Distinct()扩展名?

public IEnumerable<DirectoryPersonEntry> FindPersons(string searchTerm)
{
    DirectoryEntities dents = new DirectoryEntities();
    return (from dp in dents.DirectoryPersonEntrySet
           where dp.LastName.StartsWith(searchTerm) || dp.Extension.StartsWith(searchTerm)
           orderby dp.LastName, dp.Extension
           select dp).Distinct();
}

答案 2 :(得分:0)

您的工作和损坏查询之间的一个区别是orderby子句。我在Linq to Entities中的orderby实现中找到了documented bug ......可能还有其他人。

尝试从损坏的查询中删除orderby,看看是否仍然有重复项。

另一个区别是where子句中的OR。尝试仅使用第一部分[其中dp.LastName.StartsWith(searchTerm)]并查看是否仍然有重复项。

答案 3 :(得分:0)

我遇到了同样的问题并通过解决方法解决了这个问题。我在这里发帖,因为它可能会帮助其他人来这里。

而不是选择dp,请使用

select new <ObjectName>
{
a = v.a
b = v.b
}.

这不会返回重复项。