【问题标题】:How to Return Extra Data with IQueryable method?如何使用 IQueryable 方法返回额外数据?
【发布时间】:2014-02-26 20:21:21
【问题描述】:

我正在使用实体框架和微风。对于实体,我想与实体一起提供一些相关数据。通过查询 Entity 表并连接到其他表来最有效地获取这些数据;此查询包括 group by 子查询。

我正在尝试通过将其作为 [NotMapped] 字段添加到实体来添加这些额外数据:

[NotMapped]
public string NotMappedField { get; set; }

那么我基本上是想替换这个webapi控制器方法

[HttpGet]
public IQueryable<MyObject> MyObjects()
{
    return _contextProvider.Context.MyObjects;
}

这样的:

public IQueryable<MyObject> MyObjectsWithExtraData()
{
   var query = from o in _contextProvider.Context.MyObjects
               // big complex query
               select new MyObject
               {
                   FieldA = o.FieldA,
                   FieldB = o.FieldB,
                   // all fields
                   NotMappedField = x.ResultFromComplexJoin
               }
   return query;
}

这给了我一个错误:

无法在 LINQ to Entities 查询中构造实体或复杂类型“MyObject”。

我已经尝试了几种方法,它似乎在 EF 方面和 Breeze 方面都与我作战。我需要将其保留为返回 IQueryable 之类的内容,以便我可以通过 webapi 从客户端进行过滤,因为在此处执行 ToList() 之类的操作会由于数据集大小而导致内存问题。

所以我的问题是 - 是否有一种最佳实践方式来完成我正在尝试的事情,或者任何人都可以提供解决方案?

更新:

我发现您可以在实体旁边返回额外数据,并且仍然可以从 Breeze 中以可查询的形式访问实体:

public object MyObjectsWithExtraData()
{
    var query = from o in _contextProvider.Context.MyObjects
                // big complex query....
                select new
                {
                    theObject = MyObject,
                    NotMappedField = x.ResultFromComplexJoin
                };
    return query;
}

然后从客户端微风端你可以做这样的事情:

var query = breeze.EntityQuery
           .from("MyObjectsWithExtraData")
           .where("theObject.FieldA", "Equals", 1)
           .expand("theObject.SomeNavigationalProperty")
           .orderBy("theObject.FieldB");

仍然不是我想要的,但它实际上非常漂亮。

【问题讨论】:

  • LINQ group by on data service 的可能重复项
  • 为什么不在 HTTPResponse 中返回额外的数据,然后在完成查询后获取它?通过将参数传递给您的 .then(function (data) { console.log(data.httpResponse); } 来访问它

标签: c# linq entity-framework breeze


【解决方案1】:

看看 EntityQuery.withParameters 方法。

// client side
var q = EntityQuery.from("CustomersStartingWith")
        .withParameters({ companyName: "C" });


// server side
[HttpGet]
public IQueryable<Customer> CustomersStartingWith(string companyName) {
  var custs = ContextProvider.Context.Customers.Where(c => c.CompanyName.StartsWith(companyName));
  return custs;
}

您还可以将常规查询谓词与这些自定义参数混合并匹配。

【讨论】:

  • 谢谢杰,我并不是真的想传递参数,而是返回额外的数据。也许我可以以某种方式做到这一点 - 返回 new { MyOjbect, extraField } 并通过 data.results 获取它......将它作为实体上的未映射字段似乎更好(它只是一个额外的文本字段)
  • 仅供参考 - 我修改了问题,希望能更清楚地提出问题
【解决方案2】:

LINQ to entity 只能构造 pur "Data Transfert Object" :仅包含具有普通 getter 和 setter 且没有构造函数的公共属性的类。 在此处查看我对类似问题的回答:https://stackoverflow.com/a/21174654/3187237

我指定我的答案

无法在 LINQ to Entities 查询中实例化实体类。 如果您想在查询中构造相似(或几乎相似),则必须定义另一个类。

在您的情况下,您希望返回与您的MyObject 几乎相似的对象。所以你必须定义一个类:

public class MyObjectExtended
{
    public string FieldA { get; set; }
    public string FieldB { get; set; }
    // ... all other MyObjetc fields
    public string ExtraFieldA { get; set; }
    public string ExtraFieldB { get; set; }
}

现在,您的服务可以返回IQueryable&lt;MyObjectExtended&gt;

public IQueryable<MyObjectExtended> MyObjectsWithExtraData() {
    var myQuery = from o in _contextProvider.Context.MyObjects
        // big complex query....
        select new MyObjectExtended {
           FieldA = o.FieldA,
           FieldB = o.FieldB,
           //... all fields ...
           ExtraFieldA = x.ResultFromComplexJoinA,
           ExtraFieldB = x.ResultFromComplexJoinB
    };
    return myQuery;
}

我希望这就是你要找的。​​p>

【讨论】:

  • 如果另一个问题的答案解决了这个问题,那么这个问题应该作为那个问题的副本关闭。请相应地标记问题。
猜你喜欢
  • 2023-03-09
  • 1970-01-01
  • 2018-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-13
  • 2015-06-24
相关资源
最近更新 更多