C# 使用Lambda删除重复项

C# 使用Lambda删除重复项,c#,entity-framework,lambda,C#,Entity Framework,Lambda,我需要一些帮助来使用lambda表达式删除实体框架上下文中的重复条目。我有一个包含以下列的表: Id、事件日期、描述、员工Id、IncidentTypeId和IsAttendenceIncident 我想删除重复的条目,其中DateOfIncident、EmployeeID、incidentypeid和isattendencident是相同的。我想保留一个条目。我知道如何使用SQL中带有CTE的存储过程来完成此任务,但我不知道如何使用Lambda表达式来完成此任务 这段代码返回一个不包含重复项的

我需要一些帮助来使用lambda表达式删除实体框架上下文中的重复条目。我有一个包含以下列的表:

Id、事件日期、描述、员工Id、IncidentTypeId和IsAttendenceIncident

我想删除重复的条目,其中
DateOfIncident、EmployeeID、incidentypeid和isattendencident是相同的。
我想保留一个条目。我知道如何使用SQL中带有CTE的存储过程来完成此任务,但我不知道如何使用Lambda表达式来完成此任务

这段代码返回一个不包含重复项的列表,但现在如何删除不在此列表中的重复项

  var query = db.Incidents.Where(x => x.IsAttendanceIncident == "Y").GroupBy(x => new { x.EmployeeId, x.DateOfIncident, x.IsAttendanceIncident })
         .Select(x => x.FirstOrDefault());
更新:

所以我继续写了自定义的IEqualityComparer。现在,我如何使用id删除上下文中不属于我的特殊项的事件

 static void Main(string[] args)
    {
        DALIncidents.AttendanceEntities1 db = new DALIncidents.AttendanceEntities1();

       IEnumerable<DALIncidents.Incident> distinctItems = db.Incidents.Where(c => c.IsAttendanceIncident == "Y");
       distinctItems = distinctItems.Distinct(new DALIncidents.DistinctIncidentComparer());

       Console.ReadLine(); 
    }
static void Main(字符串[]args)
{
DALIncidents.AttendanceEntities1 db=新的DALIncidents.AttendanceEntities1();
IEnumerable differentitems=db.incents.Where(c=>c.IsAttendanceIncident==“Y”);
differentitems=differentitems.Distinct(新的DALIncidents.differentincidentcomparer());
Console.ReadLine();
}

您需要使用Distinct函数,如果您只想使用一些字段,则需要创建一个相等比较器。(IEqualityComparer)

啊,刚刚看到上面的评论,请查看以下内容:

query2现在只包含重复项

var query = db.Incidents.Where(x => x.IsAttendanceIncident == "Y").GroupBy(x => new { x.EmployeeId, x.DateOfIncident, x.IsAttendanceIncident })
     .SelectMany(x => x.Skip(1));
例1:

    .Select(x => x.FirstOrDefault());  // your original code which retrieves entities to not delete

var dupes = db.Incidents.Except( query ); // get entities to delete
例2:

    .SelectMany( x => x.OrderBy( y => y.Id ).Skip(1) ); // gets dupes directly

var dupes = query; // already have what we need
最后:

foreach( var dupe in dupes )
{
    db.Incidents.Remove( dupe );
}
从我前面使用的测试上下文生成的示例SQL,其中Person实体与watches具有1:N关系:

C#:

生成的SQL:

SELECT 
1 AS [C1], 
[Skip1].[Id] AS [Id], 
[Skip1].[Brand] AS [Brand], 
[Skip1].[Person_Id] AS [Person_Id]
FROM  [dbo].[Persons] AS [Extent1]
CROSS APPLY  (SELECT [Project1].[Id] AS [Id], [Project1].[Brand] AS [Brand], [Project1].[Person_Id] AS [Person_Id]
    FROM ( SELECT [Project1].[Id] AS [Id], [Project1].[Brand] AS [Brand], [Project1].[Person_Id] AS [Person_Id], row_number() OVER (ORDER BY [Project1].[Id] ASC) AS [row_number]
        FROM ( SELECT 
            [Extent2].[Id] AS [Id], 
            [Extent2].[Brand] AS [Brand], 
            [Extent2].[Person_Id] AS [Person_Id]
            FROM [dbo].[Watches] AS [Extent2]
            WHERE [Extent1].[Id] = [Extent2].[Person_Id]
        )  AS [Project1]
    )  AS [Project1]
    WHERE [Project1].[row_number] > 1 ) AS [Skip1]

您是否检查过是否可以使用Distinct()然后删除所有不是Distinct结果的内容(基于键)。Richard。我更新了问题。你能再看一眼吗。感谢您对IEqualityComparer的建议。这能正确地翻译成SQL吗?如果不需要,您只需指定
Where(group=>group.Count()>1)
,然后在linq to objects中执行
Skip
;使用EF并不是解决问题的最佳方案,但您询问了如何使用EF完成此任务。EF不是最优的,因为您需要检索所有数据并构造实体对象,以便通过EF发出删除命令。对不起,我以为您是原始海报。在本地创建并枚举实体对象后,将执行跳过。我已经编辑了我之前的评论,其中描述了为什么它不是最佳执行解决方案-检索所有数据,必须创建实体对象才能在数据库中删除它们。然而,最初的海报要求EF解决方案,而不是最佳性能的解决方案(即存储过程),您是正确的;skip只能用于有序查询,在这种情况下,您只需更改SelectMany lambda表达式即可对iGroup集合的项进行排序,这是可行的。我删除了这个示例,因为它只是混淆了问题。在(#2)中添加了这个示例,它只检索要删除的项目。为以下代码生成的示例SQL,其中一个人与watchs:not fit:P有1:N关系
foreach( var dupe in dupes )
{
    db.Incidents.Remove( dupe );
}
context.Persons.SelectMany(x => x.Watches.OrderBy(y => y.Id).Skip(1))
SELECT 
1 AS [C1], 
[Skip1].[Id] AS [Id], 
[Skip1].[Brand] AS [Brand], 
[Skip1].[Person_Id] AS [Person_Id]
FROM  [dbo].[Persons] AS [Extent1]
CROSS APPLY  (SELECT [Project1].[Id] AS [Id], [Project1].[Brand] AS [Brand], [Project1].[Person_Id] AS [Person_Id]
    FROM ( SELECT [Project1].[Id] AS [Id], [Project1].[Brand] AS [Brand], [Project1].[Person_Id] AS [Person_Id], row_number() OVER (ORDER BY [Project1].[Id] ASC) AS [row_number]
        FROM ( SELECT 
            [Extent2].[Id] AS [Id], 
            [Extent2].[Brand] AS [Brand], 
            [Extent2].[Person_Id] AS [Person_Id]
            FROM [dbo].[Watches] AS [Extent2]
            WHERE [Extent1].[Id] = [Extent2].[Person_Id]
        )  AS [Project1]
    )  AS [Project1]
    WHERE [Project1].[row_number] > 1 ) AS [Skip1]