转换 IQueryable<> 将对象键入 List; 类型?

发布于 2024-07-18 05:53:10 字数 342 浏览 9 评论 0 原文

我有 IQueryable 对象。

我想将其转换为 List<> ,其中包含选定的列,例如 new { ID = s.ID, Name = s.Name }

编辑

马克你是绝对正确的!

但我只能访问 FindByAll() 方法(因为我的架构)。

它给了我 IQueryable<> 中的整个对象,

而且我有严格的要求(为选择标签创建 json 对象),只有 list<> 类型和两个字段。

I have IQueryable<> object.

I want to Convert it into List<> with selected columns like new { ID = s.ID, Name = s.Name }.

Edited

Marc you are absolutely right!

but I have only access to FindByAll() Method (because of my architecture).

And it gives me whole object in IQueryable<>

And I have strict requirement( for creating json object for select tag) to have only list<> type with two fields.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

乖乖兔^ω^ 2024-07-25 05:53:11

下面是我临时组合在一起的几个扩展方法,用于将 IQueryable 和 IEnumerable 从一种类型转换为另一种类型(即 DTO)。 它主要用于从较大的类型(即数据库中具有不需要的字段的行的类型)转换为较小的类型。

这种方法的优点是:

  • 它几乎不需要使用任何代码 - 只需调用 .Transform() 即可,
  • 它的工作方式就像 .Select(s=>; new{...}) 即当与 IQueryable 一起使用时,它会生成最佳的 SQL 代码,不包括 DtoType 没有的 Type1 字段。

LinqHelper.cs:

public static IQueryable<TResult> Transform<TResult>(this IQueryable source)
{
    var resultType = typeof(TResult);
    var resultProperties = resultType.GetProperties().Where(p => p.CanWrite);

    ParameterExpression s = Expression.Parameter(source.ElementType, "s");

    var memberBindings =
        resultProperties.Select(p =>
            Expression.Bind(typeof(TResult).GetMember(p.Name)[0], Expression.Property(s, p.Name))).OfType<MemberBinding>();

    Expression memberInit = Expression.MemberInit(
        Expression.New(typeof(TResult)),
        memberBindings
        );

    var memberInitLambda = Expression.Lambda(memberInit, s);

    var typeArgs = new[]
        {
            source.ElementType, 
            memberInit.Type
        };

    var mc = Expression.Call(typeof(Queryable), "Select", typeArgs, source.Expression, memberInitLambda);

    var query = source.Provider.CreateQuery<TResult>(mc);

    return query;
}

public static IEnumerable<TResult> Transform<TResult>(this IEnumerable source)
{
    return source.AsQueryable().Transform<TResult>();
}

Here's a couple of extension methods I've jury-rigged together to convert IQueryables and IEnumerables from one type to another (i.e. DTO). It's mainly used to convert from a larger type (i.e. the type of the row in the database that has unneeded fields) to a smaller one.

The positive sides of this approach are:

  • it requires almost no code to use - a simple call to .Transform<DtoType>() is all you need
  • it works just like .Select(s=>new{...}) i.e. when used with IQueryable it produces the optimal SQL code, excluding Type1 fields that DtoType doesn't have.

LinqHelper.cs:

public static IQueryable<TResult> Transform<TResult>(this IQueryable source)
{
    var resultType = typeof(TResult);
    var resultProperties = resultType.GetProperties().Where(p => p.CanWrite);

    ParameterExpression s = Expression.Parameter(source.ElementType, "s");

    var memberBindings =
        resultProperties.Select(p =>
            Expression.Bind(typeof(TResult).GetMember(p.Name)[0], Expression.Property(s, p.Name))).OfType<MemberBinding>();

    Expression memberInit = Expression.MemberInit(
        Expression.New(typeof(TResult)),
        memberBindings
        );

    var memberInitLambda = Expression.Lambda(memberInit, s);

    var typeArgs = new[]
        {
            source.ElementType, 
            memberInit.Type
        };

    var mc = Expression.Call(typeof(Queryable), "Select", typeArgs, source.Expression, memberInitLambda);

    var query = source.Provider.CreateQuery<TResult>(mc);

    return query;
}

public static IEnumerable<TResult> Transform<TResult>(this IEnumerable source)
{
    return source.AsQueryable().Transform<TResult>();
}
两个我 2024-07-25 05:53:10

然后只需 Select:

var list = source.Select(s=>new { ID = s.ID, Name = s.Name }).ToList();

(edit) 实际上 - 在这种情况下可以推断出名称,因此您可以使用:

var list = source.Select(s=>new { s.ID, s.Name }).ToList();

这可以节省一些电子......

Then just Select:

var list = source.Select(s=>new { ID = s.ID, Name = s.Name }).ToList();

(edit) Actually - the names could be inferred in this case, so you could use:

var list = source.Select(s=>new { s.ID, s.Name }).ToList();

which saves a few electrons...

葬心 2024-07-25 05:53:10

添加以下内容:

using System.Linq

...并在 IQueryable 上调用 ToList()

Add the following:

using System.Linq

...and call ToList() on the IQueryable<>.

清风无影 2024-07-25 05:53:10

List 类的构造函数可以为您转换 IQueryable:

public static List<TResult> ToList<TResult>(this IQueryable source)
{
    return new List<TResult>(source);
}

当然,您也可以在不使用扩展方法的情况下转换它:

var list = new List<T>(queryable);

The List class's constructor can convert an IQueryable for you:

public static List<TResult> ToList<TResult>(this IQueryable source)
{
    return new List<TResult>(source);
}

or you can just convert it without the extension method, of course:

var list = new List<T>(queryable);
紫竹語嫣☆ 2024-07-25 05:53:10

System.Linq 在 IQueryable<> 上有 ToList() 和IEnumerable<>。 不过,它会导致完全遍历数据并将其放入列表中。 当您执行此操作时,您将失去延迟调用。 如果它是数据的消费者,那没什么大不了的。

System.Linq has ToList() on IQueryable<> and IEnumerable<>. It will cause a full pass through the data to put it into a list, though. You loose your deferred invoke when you do this. Not a big deal if it is the consumer of the data.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文