我试图使用EFCore 2.1.1将一个大表加入到一个小的数据对列表中。我希望这个连接发生在服务器端,而不是试图下载整个表,例如翻译成如下所示:
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中断更改,此时升级对我们来说不是一个选择(但是与更新版本相关的答案可能会帮助我们推动管理)
发布于 2022-05-12 16:41:54
如果您期望EF Core 3.x能够支持这一点,那么您就错了。如果您计划升级应用程序,最好考虑一下EF Core 6和.net 6。
不管怎样,我知道几种选择:
var items = ...
var query = context.Groups
.FilterByItems(items, (q, b) => q.organization_id == b.organization_id && q.name == i.name, true);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();发布于 2022-05-13 05:26:43
您可以使用表值参数来解决这个问题。
首先定义数据库类型;
IF TYPE_ID(N'[IdName]') IS NULL
CREATE TYPE [IdName] AS TABLE (
[Id] int NOT NULL
[Name] nvarchar(max) NOT NULL
)然后您可以从一个SqlParameter构建一个IEnumerable;
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;
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。
https://stackoverflow.com/questions/72217582
复制相似问题