首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EFCore连接值

EFCore连接值
EN

Stack Overflow用户
提问于 2022-05-12 14:37:08
回答 2查看 294关注 0票数 0

我试图使用EFCore 2.1.1将一个大表加入到一个小的数据对列表中。我希望这个连接发生在服务器端,而不是试图下载整个表,例如翻译成如下所示:

代码语言:javascript
复制
SELECT a.*
FROM Groups AS a  
INNER JOIN (VALUES (1, 'admins'), (2, 'support'), (1, 'admins')) AS b(organization_id, name)   
ON a.organization_id = b.organization_id AND a.name = b.name;  

或者类似的东西(例如使用通用的表表达式)。这个是可能的吗?如果是这样的话,是怎么做的?将对象列表传递给LINQ .join似乎总是得到客户端的处理。

由于大量的测试债务和客户端评估中的EFCore 3中断更改,此时升级对我们来说不是一个选择(但是与更新版本相关的答案可能会帮助我们推动管理)

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-05-12 16:41:54

如果您期望EF Core 3.x能够支持这一点,那么您就错了。如果您计划升级应用程序,最好考虑一下EF Core 6和.net 6。

不管怎样,我知道几种选择:

  1. 使用扩展方法FilterByItems或类似
代码语言:javascript
复制
var items = ...

var query = context.Groups
    .FilterByItems(items, (q, b) => q.organization_id == b.organization_id && q.name == i.name, true);
  1. 使用第三方扩展inq2db.EntityFrameworkCore版本2.x,请注意,我是创建者之一。它将生成与所述SQL完全相同的SQL。
代码语言:javascript
复制
var items = ...

var query = 
    from g in context.Groups
    join b in items on new { g.organization_id, g.name } equals new { b.organization_id, b.name }
    select g;

var result = query.ToLinqToDB().ToList();
票数 1
EN

Stack Overflow用户

发布于 2022-05-13 05:26:43

您可以使用表值参数来解决这个问题。

首先定义数据库类型;

代码语言:javascript
复制
IF TYPE_ID(N'[IdName]') IS NULL
    CREATE TYPE [IdName] AS TABLE (
        [Id] int NOT NULL
        [Name] nvarchar(max) NOT NULL
    )

然后您可以从一个SqlParameter构建一个IEnumerable

代码语言:javascript
复制
public class IdName
{
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }

    public static SqlParameter ToParameter(IEnumerable<IdName> values)
    {
        var meta = new SqlMetaData[]{
            new SqlMetaData(nameof(Id), SqlDbType.Int),
            new SqlMetaData(nameof(Name), SqlDbType.NVarChar, int.MaxValue)
        };

        return new SqlParameter()
        {
            TypeName = nameof(IdName),
            SqlDbType = SqlDbType.Structured,
            Value = values.Select(v => {
                var record = new SqlDataRecord(meta);
                record.SetInt32(0, v.Id);
                record.SetString(1, v.Name);
                return record;
            })
        };
    }
}

然后定义一个EF核心查询类型,您可以将该SqlParameter转换为IQueryable

代码语言:javascript
复制
public void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<IdName>(e =>
    {
        e.HasNoKey();
        e.ToView(nameof(IdName));
    });
}

public static IQueryable<IdName> ToQueryable(DbContext db, IEnumerable<IdName> values)
    => db.Set<IdName>().FromSqlInterpolated($"select * from {ToParameter(values)}");

现在,您可以在Linq中使用该IQueryable

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72217582

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档