×

Loading...
Ad by
Ad by

I re-exam the code and run unit test, and find that we can not use count linq count to do it. please see the details in content

本文发表在 rolia.net 枫下论坛In the original implementation, the adjustindex keep on update in the loop, and the updated value is used to determine if next value match the condition. (please see the adjustedIndex++ within the for loop)

int adjustedIndex = index;
List<int> orderedRemovedItemList = (from each in _removedItemIndexList
orderby each ascending
select each).ToList();
for (int i = 0; i < orderedRemovedItemList.Count; i++)
{
int removedItemPosition = orderedRemovedItemList[i];
if (removedItemPosition <= adjustedIndex)
{
adjustedIndex++;
}
}

However, in your linq query, the count is constant, and it is a fix number. the following unit test will fail with your proposal.

[Test]
public void AdjustIndex1()
{
_list.RemoveAt(0);
Expect(_list[0].ID, EqualTo(999));
Expect(_list[1].ID, EqualTo(998));
Expect(_list[2].ID, EqualTo(997));
}

[Test]
public void AdjustIndex2()
{
_list.RemoveAt(0);
_list.RemoveAt(1);
_list.RemoveAt(3);
_list.RemoveAt(5);
_list.RemoveAt(6);
Expect(_list[0].ID, EqualTo(998));
Expect(_list[1].ID, EqualTo(996));
Expect(_list[2].ID, EqualTo(993));
}

However, i really like the code your proposal. it is simple and easy-to-understand. it is the core of software development.更多精彩文章及讨论,请光临枫下论坛 rolia.net
Report

Replies, comments and Discussions:

  • 工作学习 / 学科技术讨论 / 有没有人分享一下好方法给 webservice 用 lazy loading?
    本文发表在 rolia.net 枫下论坛简单来讲就是一个 entity 带着一大堆 child entities,有 one-to-one, 也有 one-to-many

    比如
    customer
    - contact
    - orders
    - comments

    在 front-end UI 上有 multiple tab pages,只有点到 contact 的 tab 我才想 load contact entity,否则就只是最基本的 customer


    lazy loading 在 webservice 里比较麻烦的问题就是,如果 data contract 定义了所有的 children,那每次 send request, xml serialization 都会请求所有的 children 无论我的 data service logic 是不是用了什么 lazy loading method 都好。

    那最简单的方法就是(我能想到的),data contract 不定义所有的 children,但是在 presentation entity 里需要定义,并使用 xmlIgnore 掉那些 properties of child entities,我还需要有一个 ListProxy 那样的东西

    然后从原来的一个 service op:

    GetCustomerByID

    再加上

    - GetContactByCustomerID
    - GetOrdersByCustomerID
    - GetCommentsByCustomerID

    新的写法就变成

    public Contact Contact
    {
    get
    {
    if (_contact == null)
    {
    _contact = ServiceClient.GetContactByCustomerID( this.ID );
    }
    return _contact
    }
    }

    嗯,我解释得够清楚吗?

    除了这种方法,还有别的吗?

    主要是这样做,在 get 的时候还算 ok,但是在 save 的时候我需要在 data service 那里做很多特殊的处理更多精彩文章及讨论,请光临枫下论坛 rolia.net
    • 估计没啥更好的方法,个人理解EF用在web application上比较合适,基本每次操作一条记录。Window/WPF程序做比较复杂的数据处理,还是要传统的复杂处理。
      • 嗯,现在我们合同上只是做 service,对方的 front-end 是什么不都知道,只是纯粹用 message broker 软件来测试而已。如果做一个 deep loading,一个 request 要几乎十兆的数据,太慢了。客户的 legacy db 又不能碰,所以比较烦
        其实我也不是第一个遇到这样的麻烦,网上也有人问过

        http://stackoverflow.com/questions/5762135/ef4-cause-circular-reference-in-web-service/5763627#5763627


        但那里提到的方法基本也是我想的方法

        估计以现在的技术是没有什么其他的了
    • 我想不出来你在save的时候要做什么特殊的处理。如果你是存customer信息的时候要改变contact的内容,那你怎么都避免不了;不改的话,要多处理什么?
      • 嗯,说错了,不是在 data service 上处理,是 service agent。因为那些 children 不再是 datamember 直接会被 serialized,那么我在 service agent 那里需要做(见内)。然后问题就是,我不能做 transaction 了
        save ()
        {

        serviceClient.SaveCustomer()

        if (this.Contact.IsLoaded && this.Contact.IsChanged)
        serviceClient.SaveContact( this.CustomerID, this.Contact )


        }


        这里的问题是,我没有办法把所有的 save 在 data service 那里放在一个 transaction 里面了
        • WCF支持client's transaction的。==>
          • you are right, haha
      • 问得好,我差点就忘了 saving 要 transaction 的问题了。有什么好方法吗?
        • 我做的话,会分别写save, saveCustomer(), saveContact(), saveOrder(),"serviceClient.SaveContact( this.CustomerID, this.Contact ) ",Contact里面已经有customerID了,不用再显示的call了。
          • 你的意思是 multiple service operation contracts? 嗯,我觉得可能 transaction 并不是一个大问题,因为就算从上到下,中间有一个 child entity fails to save due to business logic failure,那至少可以 save others
          • haha, 刚才下载了一本 entity framework in action,里面居然有一张是讲 lazy loading when serializing 的,有意思有意思
    • i wrote some articles about handle large data using virtual list and paged data, it does not related with EF, but it might help.
      • 不错,体现lazy loading的思想。
      • very nice work, very useful for paging, however, doesn't really apply the case of one entity with over 30 children entities
        本文发表在 rolia.net 枫下论坛and those children might even have cascade relationship
        some children are 1-to-1, some are 1-to-many

        however, I do agree I can adopt your method, basically similar to how I solve it before

        I was planning to create a bunch DTOs

        for example, originally, I have

        Employee
        - EmployeeEnrollment (1-to-many)
        - EmployeeDependent (1-to-many)
        - other 30 children

        and one service operation each for CRUD

        GetEmployee : Employee

        If call this service op, it will serialize the request for all children, then fetch everything back from the service side (BAD)

        My plan was to have

        - EmployeeDTO
        - EmployeeEnrollmentDTO
        - EmployeeDependent

        these DTO objects have no relationship, purely represents the table only

        and I still have one operation GetEmployee : Employee, but internally, it becomes

        return serviceClient.GetEmployeeDTO ( id ).ToEmployee()

        so in my service agent, I have to translate the fetched DTO to the real entity

        now, each child entity will need to have a virtual list, similar to what you do, if the entity has not been loaded, I will launch another DTO call, i.e. GetEmployeeEnrollmentDTO ( employeeId ) , then translate it

        so I will end up having a lot of sub-service operations and more entities, but I can use t4 to generate them, that's not really a big problem

        what do u think of it?更多精彩文章及讨论,请光临枫下论坛 rolia.net
        • sound good. it will work
      • private int AdjustIndex(int index),里面又是linq又是foreach,可以简洁点吧。return index + (from each in _removedItemIndexList).where(x=>x<index;).count();
        • well, the AdjustIndex() implementation you suggested is much better than my previous implementation. thank you so much for the suggestion.
        • I re-exam the code and run unit test, and find that we can not use count linq count to do it. please see the details in content
          本文发表在 rolia.net 枫下论坛In the original implementation, the adjustindex keep on update in the loop, and the updated value is used to determine if next value match the condition. (please see the adjustedIndex++ within the for loop)

          int adjustedIndex = index;
          List<int> orderedRemovedItemList = (from each in _removedItemIndexList
          orderby each ascending
          select each).ToList();
          for (int i = 0; i < orderedRemovedItemList.Count; i++)
          {
          int removedItemPosition = orderedRemovedItemList[i];
          if (removedItemPosition <= adjustedIndex)
          {
          adjustedIndex++;
          }
          }

          However, in your linq query, the count is constant, and it is a fix number. the following unit test will fail with your proposal.

          [Test]
          public void AdjustIndex1()
          {
          _list.RemoveAt(0);
          Expect(_list[0].ID, EqualTo(999));
          Expect(_list[1].ID, EqualTo(998));
          Expect(_list[2].ID, EqualTo(997));
          }

          [Test]
          public void AdjustIndex2()
          {
          _list.RemoveAt(0);
          _list.RemoveAt(1);
          _list.RemoveAt(3);
          _list.RemoveAt(5);
          _list.RemoveAt(6);
          Expect(_list[0].ID, EqualTo(998));
          Expect(_list[1].ID, EqualTo(996));
          Expect(_list[2].ID, EqualTo(993));
          }

          However, i really like the code your proposal. it is simple and easy-to-understand. it is the core of software development.更多精彩文章及讨论,请光临枫下论坛 rolia.net
      • 另外,"[Appendix] Here is full source code. It is built by visual studio 2010."觉的应该是built in visual studio 2010
        • thanks. good suggestion. i have updated it. and move the download to top of the article.
    • 老大,中介给我发一个75$/h的Silverlight职位,愿意做就pm我
      • thanks!!! but pass, after having a baby, i just want to stay at home everyday :)