【问题标题】:Foreach updates every record in a LINQ resultForeach 更新 LINQ 结果中的每条记录
【发布时间】:2015-11-10 09:26:53
【问题描述】:

我使用 WCF 数据服务通过分页获取数据。

我必须为客户提供一个特定的对象(ExtraData),但在数据库中,没有这样的数据。它是几个表的组合数据,它有 1 行以使其可交叉连接。

由于 WCF 数据服务不允许创建动态对象,因此返回的数据必须在查询中。

服务以客户需要的形式返回更新后的数据。

我有以下方法:

[WebGet]
public IQueryable<ExtraData> GetExtraData(string groupID)
{
 var query= (from data in context.Data                           
            join information in context.Information on information.ID equals data.InformationID into tempInformation
            from information in tempInformation.DefaultIfEmpty()
            from extraData in context.ExtraData // cross-joining the dummy
            where data.GroupID == groupID
            select new
            {
             ExtraData = extraData,
             Data = data,
             InformationText = information.Text
            }).ToList();

//After the execution, I intend to modify the result (as it is a dummy record yet):

 query.ForEach(
      item =>
      {       
          item.ExtraData.DataID = item.Data.ID;
          item.ExtraData.Name = item.Data.NameAux; 
          item.ExtraData.Group = elem.Data.ExtraGroup;       
      }
      );

  return (from item in query
              select item.ExtraData).AsQueryable();
}

不幸的是,它每次都会修改每条记录,所以我最终会多次获得相同的记录。

我应该修改什么以使ExtraData 记录唯一?

更新:

在 foreach 中,我得到以下数据:

3ca65876-c88f-4849-bef5-170e62f084ec Name16
b705ebc3-8245-4c16-8045-a79ef15192d2 Name16
b8bb423c-02ff-4e9a-b941-a20a9c69dd12 Name Second 16
4e3d3496-4b36-4dab-b471-a43ffb075345 Other16
f93a2358-818e-4929-a51a-46a7b7080bd4 Test16
a4bca994-73d2-4d0e-a18a-2539067a7498 Test Second 16
c7474a92-430a-46ad-bc3d-7e526dfb2647 New Test 16
6117f1b6-3f6b-4fae-b448-2778d68d0877 New Test Mod 16
8e831455-4305-4ee3-b56d-3b0e23131df8 Test Mod 16

在结果集中,我得到了这个:

<entry><id>http://localhost/MyService/Service.svc/ExtraData(guid'8e831455-4305-4ee3-b56d-3b0e23131df8')</id><category term="ExtraData" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /><link rel="edit" title="ExtraData" href="ExtraData(guid'8e831455-4305-4ee3-b56d-3b0e23131df8')" /><title /><updated>2015-11-10T10:07:36Z</updated><author><name /></author><content type="application/xml"><m:properties><d:ID m:type="Edm.Guid">8e831455-4305-4ee3-b56d-3b0e23131df8</d:ID><d:Name>Test Mod 16</d:Name><d:Group m:type="Edm.Int32">1</d:Group></m:properties></content></entry>
<entry><id>http://localhost/MyService/Service.svc/ExtraData(guid'8e831455-4305-4ee3-b56d-3b0e23131df8')</id><category term="ExtraData" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" /><link rel="edit" title="DSPaciens" href="ExtraData(guid'8e831455-4305-4ee3-b56d-3b0e23131df8')" /><title /><updated>2015-11-10T10:07:36Z</updated><author><name /></author><content type="application/xml"><m:properties><d:ID m:type="Edm.Guid">8e831455-4305-4ee3-b56d-3b0e23131df8</d:ID><d:Name>Test Mod 16</d:Name><d:Group m:type="Edm.Int32">1</d:Group></m:properties></content></entry>

【问题讨论】:

  • 你真的需要交叉加入 ExtraData 吗?这造成很多记录。 ExtraData = new ExtraData() 就够了吗?
  • 我无法使用任何实例化,因为数据服务无法创建新实体。它必须在查询中。它包含一行,因此交叉连接不会产生额外的记录,只会产生额外的列。
  • 好吧,您正在创建一个交叉连接(有意)。你为什么不直接删除它?另请注意,这些并非都是不同的 ExtraData 对象。数据库中的每一行只有一个这样的对象。您多次编写相同的对象。
  • 您一般想要达到什么目的?
  • 好的,我明白了。为什么不在 ForEach 中手动创建对象?为什么不允许这样做?无论如何,您都不会返回真正的查询。您正在返回一个与数据库断开连接的“假查询”。

标签: c# linq wcf-data-services


【解决方案1】:

嗯,我们已经非常接近解决方案了 :)

关键元素是@usr 写的:

数据库中的每一行只有一个这样的对象。你在写 多次重复相同的对象。

不幸的是,选择的匿名对象是只读的,所以我必须创建一个包含必要数据的包装类:

public class CombinedData
{
   public ExtraData ExtraData { get; set; }
   public Data Data { get; set; }
   public string InformationText {get; set; }
}

然后在查询中使用它:

var query= (from data in context.Data                           
            join information in context.Information on information.ID equals data.InformationID into tempInformation
            from information in tempInformation.DefaultIfEmpty()
            from extraData in context.ExtraData // cross-joining the dummy
            where data.GroupID == groupID
            select new CombinedData
            {
             ExtraData = extraData,
             Data = data,
             InformationText = information.Text
            }).ToList();

然后在 ForEach 循环内创建一个新的 ExtraData 对象:

query.ForEach(
      item =>
      {   
          item.ExtraData=new ExtraData();    
          item.ExtraData.DataID = item.Data.ID;
          item.ExtraData.Name = item.Data.NameAux; 
          item.ExtraData.Group = elem.Data.ExtraGroup;       
      }
      );

现在,它可以工作了。感谢您为我指明正确的方向:)

【讨论】:

  • 是的,这也有效。不过,我宁愿建议一种不同的模式:return query.AsEnumerable().Select(x =&gt; new { ... }).AsQueryable();。并适当填写...。这会产生更好的代码。更少的副作用和突变,不会滥用实体类作为 DTO。
  • 同意,您的方法要好得多。但是,在给定的情况下,我的实体类充当 DTO(出于目的,它不会创建或更新现有的数据库记录),所以我使用上面的代码。感谢您的大力帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多