仅选择具有Linq(EF核心)的特定字段 [英] Select only specific fields with Linq (EF core)
问题描述
我有一个 DbContext
,我想在其中运行查询以仅返回特定的列,以避免获取所有数据.
问题是我想用一组字符串指定列名,并且我想获得原始类型的 IQueryable
,即不构造匿名类型.
I have a DbContext
where I would like to run a query to return only specific columns, to avoid fetching all the data.
The problem is that I would like to specify the column names with a set of strings, and I would like to obtain an IQueryable
of the original type, i.e. without constructing an anonymous type.
这里是一个例子:
// Install-Package Microsoft.AspNetCore.All
// Install-Package Microsoft.EntityFrameworkCore
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
public class Person {
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class TestContext : DbContext {
public virtual DbSet<Person> Persons { get; set; }
public TestContext(DbContextOptions<TestContext> options) : base(options) {
}
}
class Program {
static void Main(string[] args) {
var builder = new DbContextOptionsBuilder<TestContext>();
builder.UseInMemoryDatabase(Guid.NewGuid().ToString());
var context = new TestContext(builder.Options);
context.Persons.Add(new Person { FirstName = "John", LastName = "Doe" });
context.SaveChanges();
// How can I express this selecting columns with a set of strings?
IQueryable<Person> query = from p in context.Persons select new Person { FirstName = p.FirstName };
}
}
我想使用这种方法:
static IQueryable<Person> GetPersons(TestContext context, params string[] fieldsToSelect) {
// ...
}
有没有办法做到这一点?
Is there a way I can do this?
推荐答案
由于您要投影(选择)类型为 T
的成员,使其与类型为 T
的成员相同,所需的 Expression< Func< T,T>>
可以使用这样的 Expression
类方法相对容易地创建:
Since you are projecting (selecting) the members of the type T
to the same type T
, the required Expression<Func<T, T>>
can relatively easy be created with Expression
class methods like this:
public static partial class QueryableExtensions
{
public static IQueryable<T> SelectMembers<T>(this IQueryable<T> source, params string[] memberNames)
{
var parameter = Expression.Parameter(typeof(T), "e");
var bindings = memberNames
.Select(name => Expression.PropertyOrField(parameter, name))
.Select(member => Expression.Bind(member.Member, member));
var body = Expression.MemberInit(Expression.New(typeof(T)), bindings);
var selector = Expression.Lambda<Func<T, T>>(body, parameter);
return source.Select(selector);
}
}
Expression.MemberInit 是 new T {Member1 = x.Member1,Member2 = x.Member2,...}
C#构造的等效表达式.
Expression.MemberInit is the expression equivalent of the new T { Member1 = x.Member1, Member2 = x.Member2, ... }
C# construct.
示例用法为:
return context.Set<Person>().SelectMembers(fieldsToSelect);
这篇关于仅选择具有Linq(EF核心)的特定字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!