Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/elixir/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 实体框架-删除重复项_C#_.net_Entity Framework_Asp.net Core_Entity Framework Core - Fatal编程技术网

C# 实体框架-删除重复项

C# 实体框架-删除重复项,c#,.net,entity-framework,asp.net-core,entity-framework-core,C#,.net,Entity Framework,Asp.net Core,Entity Framework Core,我想使用实体框架删除重复记录 这就是我尝试过的 var result = _context.History .GroupBy(s => new { s.Date, s.EventId }) .SelectMany(grp => grp.Skip(1)).ToLis

我想使用实体框架删除重复记录

这就是我尝试过的

var result = _context.History
            .GroupBy(s => new
                    {
                        s.Date,
                        s.EventId
                    })
            .SelectMany(grp => grp.Skip(1)).ToList();

_context.History.RemoveRange(result);
await _context.SaveChangesAsync();
但我犯了个错误

System.InvalidOperationException:由“NavigationExpandingExpressionVisitor”处理LINQ表达式“grp=>grp.Skip(1)”失败。这可能表明EF Core中存在缺陷或限制


我知道这是对Entity Framework的破坏性更改,但我真的不知道如何更新我的代码。

看起来Entity Framework不知道如何翻译这个
跳过
LINQ查询的一部分。此外,它不能将此
GroupBy
部分转换为translate。在EF Core 3中,它将抛出一个异常以让我们知道:)

因此,一种肮脏但简单的方法是几乎在开始时添加
AsEnumerable
,然而,它将获取所有表并在内存中执行操作:

var result = _context.History
            .AsEnumerable()
            .GroupBy(s => new { s.Date, s.EventId })
            .SelectMany(g => g.Skip(1))
            .ToList();

_context.History.RemoveRange(result);
await _context.SaveChangesAsync();
因为在大多数情况下,获取我们能获取的所有内容是不可接受的将第一个请求分成两个,这样我们就只能下载重复的记录

第二个答案可能会有所帮助,我们可以尝试以下方法:

var keys = _context.History
                .GroupBy(s => new { s.Date, s.EventId })
                .Select(g => new { g.Key, Count = g.Count() })
                .Where(t => t.Count > 1)
                .Select(t => new { t.Key.Date, t.Key.EventId })
                .ToList();

var result = _context.History
    .Where(h => keys.Any(k => k.Date == h.Date && k.EventId == h.EventId))
    .AsEnumerable()
    .GroupBy(s => new { s.Date, s.EventId })
    .SelectMany(g => g.Skip(1))
    .ToList();

_context.History.RemoveRange(result);
await _context.SaveChangesAsync();

看起来实体框架不知道如何翻译LINQ查询的
Skip
部分。此外,它不能将此
GroupBy
部分转换为translate。在EF Core 3中,它将抛出一个异常以让我们知道:)

因此,一种肮脏但简单的方法是几乎在开始时添加
AsEnumerable
,然而,它将获取所有表并在内存中执行操作:

var result = _context.History
            .AsEnumerable()
            .GroupBy(s => new { s.Date, s.EventId })
            .SelectMany(g => g.Skip(1))
            .ToList();

_context.History.RemoveRange(result);
await _context.SaveChangesAsync();
因为在大多数情况下,获取我们能获取的所有内容是不可接受的将第一个请求分成两个,这样我们就只能下载重复的记录

第二个答案可能会有所帮助,我们可以尝试以下方法:

var keys = _context.History
                .GroupBy(s => new { s.Date, s.EventId })
                .Select(g => new { g.Key, Count = g.Count() })
                .Where(t => t.Count > 1)
                .Select(t => new { t.Key.Date, t.Key.EventId })
                .ToList();

var result = _context.History
    .Where(h => keys.Any(k => k.Date == h.Date && k.EventId == h.EventId))
    .AsEnumerable()
    .GroupBy(s => new { s.Date, s.EventId })
    .SelectMany(g => g.Skip(1))
    .ToList();

_context.History.RemoveRange(result);
await _context.SaveChangesAsync();

在这种情况下,您将按两列进行分组:

var duplicate = DB.History.GroupBy(x => new { x.Date, x.EventId})
                         .Where(x => x.Count() > 1)
                         .SelectMany(x => x.ToList());

在这种情况下,您将按两列进行分组:

var duplicate = DB.History.GroupBy(x => new { x.Date, x.EventId})
                         .Where(x => x.Count() > 1)
                         .SelectMany(x => x.ToList());

首先不要使用EF Core。EF核心是ORM,而不是SQL的替代品。这里没有对象,删除重复项的最简单、最有效的方法是使用CTE,其中包含
ROW_NUMBER()
,该CTE将返回所有的倍数,按您想要的排序顺序排列,允许您选择要保留的行
,其中dup为(选择*,ROW_NUMBER()(按日期划分,事件id顺序按id描述)rn from…)delete DUP,其中rn>1
将删除除最大id以外的所有重复项。CTE不需要返回所有列,只需返回键列即可。您可以指定不同的
排序依据
,以选择要排序的不同行preserve@PanagiotisKanavos这个CTE数据库是不可知的还是特定于SqlServer?ORM可能不是SQL的替代品,但LINQ应该是抽象和数据库无关的集成查询语言,所以为什么不使用它呢?EF Core因不愿意翻译而违反合同的事实并不意味着OP做了错事。@IvanStoev操作不是对象不可知论的。没有涉及任何对象。林克不该处理这种情况。ORMs从来就不是用来报告查询或完全替代SQL的。如果用
ANSI标准
替换
数据库不可知
,是的,它是ANSI标准,甚至在MySQL 8之后的MySQL中也受支持。所有其他主要数据库都有
行号()already@IvanStoevSQLite在中添加了窗口功能。此外,OP试图做的事情在SQL中没有意义-该组不是真正的分组,SQL中没有跳过。这是试图将LINQ to Objects操作应用到数据库(效率有点低),希望EF Core能够以某种方式将其转换为SQLCore,而不是首先使用EF Core。EF核心是ORM,而不是SQL的替代品。这里没有对象,删除重复项的最简单、最有效的方法是使用CTE,其中包含
ROW_NUMBER()
,该CTE将返回所有的倍数,按您想要的排序顺序排列,允许您选择要保留的行
,其中dup为(选择*,ROW_NUMBER()(按日期划分,事件id顺序按id描述)rn from…)delete DUP,其中rn>1
将删除除最大id以外的所有重复项。CTE不需要返回所有列,只需返回键列即可。您可以指定不同的
排序依据
,以选择要排序的不同行preserve@PanagiotisKanavos这个CTE数据库是不可知的还是特定于SqlServer?ORM可能不是SQL的替代品,但LINQ应该是抽象和数据库无关的集成查询语言,所以为什么不使用它呢?EF Core因不愿意翻译而违反合同的事实并不意味着OP做了错事。@IvanStoev操作不是对象不可知论的。没有涉及任何对象。林克不该处理这种情况。ORMs从来就不是用来报告查询或完全替代SQL的。如果用
ANSI标准
替换
数据库不可知
,是的,它是ANSI标准,甚至在MySQL 8之后的MySQL中也受支持。所有其他主要数据库都有
行号()already@IvanStoevSQLite在中添加了窗口功能。此外,OP试图做的事情在SQL中没有意义-该组不是真正的分组,SQL中没有跳过。这是在尝试将LINQtoObjects操作应用到数据库中(有点低效),希望EFCore能够以某种方式将其转换为SQLHello,欢迎使用SO。这是我得到的错误
System.invalidoOperationException:客户端GroupBy不受支持。
有趣的是,我不知道这一点,但看起来在EF Core 3中,他们添加了一个显式错误,因为
GroupBy
没有被转换为SQL,这里的第二个答案非常好:最简单的解决方案是移动
AsEnumerable()
\u context.History
之后的右上角。但是,它会将此表中的所有数据提取到服务器,并在内存中执行所有操作。你的情况可以接受吗?我已经更新了答案,以便你更容易理解我的问题