Issues related with Linq in CSLA

Issues related with Linq in CSLA

Old forum URL: forums.lhotka.net/forums/t/7547.aspx


Vinodonly posted on Tuesday, September 01, 2009

I'm doing some filtering based on the selection by user on my BLB.. I have designed UI related classes in a generic way so that it can work on all the BO's..

My problem is that once I use the linq query, the returned object is linqbindinglist...

If I try to cast it to Linqbindinglist then it fails...

I want to get 2 properties from each bo i.e. IsSavable and IsDirty, How I can get it from the linq result in a generic way

Vinodonly replied on Tuesday, September 01, 2009

I found one more issue which i think is related with the previous problem.

I'm using following linq query..

from OC in OrderColors
where OC.SomeValue = "XYZ"
Select OC;

OrderColors is Business ListBase which is having OrderColor objects..

The above query is returning linqbindinglist with T param as OrderColor instead of OrderColors. This is creating problems which adding new record etc. is failing..

How I can modify the above linq query to return linqbindinglist of OrderColors instead of OrderColor.

RockfordLhotka replied on Tuesday, September 01, 2009

If you start with a List<T> and do a normal LINQ query you'll get back an IEnumerable<T>.

The 'T' type is the type of the items contained in the list.

If you start with a List<T> and do a L2C query you'll get back a LinqBindingList<T>.

Again, the 'T' type is the type of the items contained in the list.

Never does LINQ return a list of the original list type - well, not unless you started with a basic IEnumerable<T> - and even then you'll get back a different instance of the same type.

Vinodonly replied on Wednesday, September 02, 2009

Although I understood your point theoritically but i'm still blank on practical side of it..

Taking the same example, if i want to get OrderColors collection back even as a different instance type then how the query will be formed..

I tried different combinations but was not able to get that..

The problem is that AddNewCore and other required methods are in parent collection so that is needed..

I also want to point that although the book is having a dedicated chapter on this thing but how this is to be used practically is not given..

are there any posts or links where this is given with some examples so it is little clear..

I'm using linq for other objects and this was my first attempt in using it with csla..

Vinodonly replied on Wednesday, September 02, 2009

After trying various tests, I found following issues but was not able to find solution

1. How to form a query which can get the Original Collection i.e. OrderColors of BLB.

2. If I modify program to support LinqBindingList of type Ordercolor then in ordercolor, parent object is set to null which is throwing error.

3. If I try to cast the result of Linqbindinglist in a generic way i.e. casting it to ItrackStatus or IEditableBusinessobject then it is throwing error, so how I can get the IsSavable and IsDirty properties in a generic way so it can work for all bo's.

RockfordLhotka replied on Wednesday, September 02, 2009

Vinodonly:

1. How to form a query which can get the Original Collection i.e. OrderColors of BLB.

You can't, because LINQ doesn't work that way. LINQ creates and returns a new list - typically an IEnumerable<T> (the simplest list type in .NET), and L2C sometimes makes it return a LinqBindingList<T>.

Vinodonly:

2. If I modify program to support LinqBindingList of type Ordercolor then in ordercolor, parent object is set to null which is throwing error.

If you have a LinqBindingList, it should act as a view over the original list. In other words adding an item to the LBL adds it to the original list, removing an item from the LBL removes it from the original list, etc.

If you can provide a specific unit test showing a failure condition I'll loop Aaron into this thread so he can help troubleshoot/fix the issue.

Vinodonly:

3. If I try to cast the result of Linqbindinglist in a generic way i.e. casting it to ItrackStatus or IEditableBusinessobject then it is throwing error, so how I can get the IsSavable and IsDirty properties in a generic way so it can work for all bo's.

LBL doesn't implement those interfaces. It is not a replacement for the original list, it is a view over the original list.

Any sort of persistence or complex interactions still need to be done on the original list, not on the view.

LBL is designed to give you a view of the original list that can be databound to a datagrid, supporting data binding, adding, editing and removing items from the original list, but through the view.

But it is a view and is not a replacement for the original list.

Vinodonly replied on Wednesday, September 02, 2009

Thanks for your help.. This cleared lot of doubts..

Reg Point 2 :- If we run a linq query as mentioned in my previous posts, then in the ChildPortal_Fetch, this.parent ref is set to null..

I'm getting some values from Parent collection but when I use linq query then bcos the parent ref is null, it is throwing errors.

Reg Point 3 :- What I understand is that with Linqbindinglist, we cannot get to the original object properties which is contained in that, Pls correct me if I'm wrong...

RockfordLhotka replied on Wednesday, September 02, 2009

I don't completely understand what you are trying to do, or where you are
using L2C.

The Parent property of a child is set when it is added to the original list.
BusinessListBase sets the Parent property as the child is added. If the
child isn't added to the original list, then Parent wouldn't be set.

If you are using a LBL, it would be a view over a BLB. When you add an item
to the LBL, it should automatically get added to the underlying BLB, which
should trigger setting the Parent property.

If that is not happening, please provide a small unit test that illustrates
the problem as it could be a bug.

Vinodonly replied on Thursday, September 03, 2009

After your reply, I'm sure that this is a bug..

Here is what I'm doing to reproduce this problem also..

I have a businesslistbase called ordercolors with ordercolor as businessbase. When user gets the record first time, all recs are retreived from db i.e. normal bo retrieval without linq.

On top of the form there are filtering options for 2 fields i.e. Type and Tag..

Once user chooses filtering option then linq is executed (same query which I gave before). Filtered records are shown to user, where he can do entries for that particular Type or Tag...

Now when he tries to add a record, Child_Create is called, which gets some info using this.parent.. In linq query, this is not getting properly set whereas in normal bo's ref is auto set properly..

Hope this is clear..

RockfordLhotka replied on Thursday, September 03, 2009

This test passes:

 

      var list = TestCollection.GetList();

      Assert.AreEqual(list.Count, 5);

 

      var filtered = from r in list

                     where r.Id > 10

                     select r;

      Assert.AreEqual(filtered.Count(), 3);

 

      var lbl = filtered as Csla.LinqBindingList<TestItem>;

      Assert.IsNotNull(lbl);

      Assert.AreEqual(lbl.Count, 3);

 

      var @new = (TestItem)lbl.AddNew();

      Assert.AreEqual(list.Count, 6);

      Assert.AreEqual(lbl.Count, 3);

      Assert.IsTrue(@new.HasParent());

 

Where TestCollection has AllowNew=true and an AddNewCore() override that calls DataPortal.CreateChild<TestItem>(). The TestItem class has a HasParent() method like this:

 

    public bool HasParent()

    {

      return (Parent != null);

    }

 

You can see the full AddNewItemToLBL() test here:

http://www.lhotka.net/cslacvs/viewvc.cgi/trunk/cslatest/Csla.Test/Basic/CollectionTests.cs?view=markup

 

 

Vinodonly replied on Thursday, September 03, 2009

I’m out of office now and will be back on Saturday.. from my side I did the testing and it was giving error. In any case, I will rechk this test as well as my code and post final reply on Saturday..

Copyright (c) Marimer LLC