Skip to main content
 首页 » 编程设计

C# Web API LINQ 实体查询之将 AnonymousType 转换为类对象

2024年02月01日29kenshinobiy

我有以下代码:

public List<Product> ListAll() 
{ 
    List<Product> products = new List<Product>(); 
 
    var db_products = db.Products 
        .Where(p => p.Enabled == true) 
        .OrderBy(p => p.Name) 
        .Select(p => new 
        { 
            ProductId = p.ProductId, 
            Name = p.Name, 
            ... 
        }) 
        .ToList(); 
 
    foreach (var dbP in db_products) 
    { 
        Product p = new Product(); 
        p.ProductId = dbP.ProductId; 
        p.Name = dbP.Name; 
        ... 
        products.Add(p); 
    } 
 
    return products; 
} 

它如我所愿地工作,因为它成功地返回了一个产品对象列表。不过,有没有没有 foreach 循环的方法,所以我可以立即转换它?

我试过:

public List<Product> ListAll() 
{ 
    List<Product> products = db.Products 
        .Where(p => p.Visible == true) 
        .OrderBy(p => p.Name) 
        .Select(p => new 
        { 
            ProductId = p.ProductId, 
            Name = p.Name, 
            ... 
        }) 
        .AsEnumerable() 
        .Cast<Product>() 
        .ToList(); 
 
    return products; 
} 

和

public List<Product> ListAll() 
{ 
    List<Product> products = db.Products 
        .Where(p => p.Visible == true) 
        .OrderBy(p => p.Name) 
        .Select(p => new Product 
        { 
            ProductId = p.ProductId, 
            Name = p.Name, 
            ... 
        }) 
        .ToList(); 
 
    return products; 
} 

但两者都不起作用。对于第二个,我收到以下错误:

at System.Data.Objects.ELinq.ExpressionConverter.CheckInitializerType(Type type) 
   at System.Data.Objects.ELinq.ExpressionConverter.MemberInitTranslator.TypedTranslate(ExpressionConverter parent, MemberInitExpression linq) 
   at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) 
   at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 
   at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input) 
   at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding) 
   at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda) 
   at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) 
   at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod) 
   at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 
   at System.Data.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) 
   at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 
   at System.Data.Objects.ELinq.ExpressionConverter.Convert() 
   at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption) 
   at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) 
   at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() 
   at System.Data.Entity.Internal.Linq.InternalQuery`1.GetEnumerator() 
   at System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.Generic.IEnumerable<TResult>.GetEnumerator() 
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) 
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) 
   at SeashellBrawlCorvee...ListAll() in c:\Users\...\Documents\Visual Studio 2012\Projects\seashell-brawl-corvee\seashell-brawl-corvee\...\ProductController.cs:line 149 
   at SeashellBrawlCorvee...ProductsRepository..ctor() in c:\Users\...\Documents\Visual Studio 2012\Projects\seashell-brawl-corvee\seashell-brawl-corvee\...\ProductsRepository.cs:line 21 
   at SeashellBrawlCorvee...ProductsController..cctor() in c:\Users\...\Documents\Visual Studio 2012\Projects\seashell-brawl-corvee\seashell-brawl-corvee\...\ProductsController.cs:line 16 

如果有人知道解决方案,我将不胜感激,否则我将坚持使用 foreach 循环。

预先感谢您的回复。

请您参考如下方法:

当你从一个ORM调用一个方法时,它可以返回一个代理,所以,当web api需要反序列化它时,你会遇到很多问题。

一种方法是创建一个 ViewModel .例如,使用您需要的信息创建一个类:

public class ProductViewModel 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
    // properties 
} 

当您查询数据时,尝试返回 List<ProductViewModel> , 例如:

return db.Products 
    .Where(p => p.Visible == true) 
    .OrderBy(p => p.Name) 
    .Select(p => new ProductViewModel() { Id = p.ProductId, Name = p.Name }) 
    .ToList(); 

使用 ViewModel暴露于 View或 Request是一个很好的实践。