代码之家  ›  专栏  ›  技术社区  ›  ProfK

当数据与LINQ绑定到实体时重复行

  •  12
  • ProfK  · 技术社区  · 16 年前

    我在将telerik radgrid和普通的ASP.NET网格视图绑定到以下linq to entities查询的结果时遇到问题。在这两种情况下,网格都包含正确的行数,但只有前几行的数据在所有其他行中都是重复的。我将直接从该代码中分配返回值网格上的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;
    }
    

    补充: 这是可工作的备用普通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会导致调用方法在绑定之前产生相同的重复。

    更新 : 基于来自 马克砾石 下面,我发现EF设计师对我的实体类的实体键做了一个非常不受教育的猜测,实体类是其字段列表中的第一个字段,Department,其中只有大约七个条目在所有其他记录中共享。

    这确实是重复的原因。如果我可以更改或删除实体键,但这个EF设计师的所有业务逻辑蚀刻素描是令人钦佩的承诺,重复它的延迟选择键,而笑我锁在外面乞求更改键。

    4 回复  |  直到 16 年前
        1
  •  30
  •   Marc Gravell    16 年前

    在我看来,你有一把借来的主键。linq-to-sql和ef的“标识管理”方面意味着,每当它看到相同对象类型的相同主键值时,就必须返回相同的实例。

    例如,给定数据:

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

    然后 如果它认为 id 是主键 当从Linq迭代对象时,它是 强迫 给你“弗雷德”、“巴尼”、“弗雷德”、“弗雷德”。基本上,当它看到 身份证件 1同样,它甚至不查看其他列-它只是用 身份证件 1来自身份缓存-并提供与之前相同的fred实例。如果它 认为 身份证件 是主键,它将把每一行视为一个单独的对象(如果其中一个字段中的值与另一个记录中的值相同,那又会怎样呢——这并不罕见)。

    我建议检查您标记为主键的任何字段(在DBML/EDM模型中)是否每行都是唯一的。在上述情况下, 身份证件 列显然不表示唯一标识符,因此不适合作为主键。只需在linq to sql/ef设计器中将其取消标记。


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

        2
  •  1
  •   StevenMcD    16 年前

    如果您将链接查询括在括号中并使用.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();
    }
    
        3
  •  0
  •   Handcraftsman    16 年前

    工作查询和中断查询之间的一个区别是orderby子句。我找到了一个 documented bug 在LINQ to Entities中的orderby实现中…可能还有其他的。

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

    另一个区别是WHERE子句中的OR。尝试只使用第一部分[其中dp.lastname.startswith(searchterm)],然后查看是否仍有重复项。

        4
  •  0
  •   franklins    14 年前

    我也面临同样的问题,并通过一个变通办法解决了它。我把它贴在这里,因为它可能会帮助其他人来这里。

    不要选择dp,而是使用

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

    这不会返回重复项。