locked
IList<T>, IEnumerable<T> or BindingList<T> in the layers of N-Layer application using LINQ to SQL in the data source layer? RRS feed

  • Question

  • Hi. I need some feedback of using an IList<T> vs a BindingList<T> in my application. I'm developing a N-Layer WinForms application in Visual C# 2008 Express Edition in which I'm implementing the Model View Presenter (MVP) pattern with the Supervising Controller approach (with data binding) for the presentation layer, a thin service layer, a Domain Model for the domain layer, and LINQ to SQL for the data source layer in which I’m using POCO classes in the domain layer.

    Currently, the queries in my application return IList<T> in which T are the entities. However, in the UI of my application I will need to use several dozens of DataGridView (and also MS Charts) in which I will need to be able to click on any header of the columns with simple types (int, decimal, string and DateTime) in order to see the data sorted by ascending order or descending order. I believe that I need to use a BindingList<T> in order to be able to do that.  If using IList<T> I’m not able to get that functionality. In order to fix this I think that I have 2 alternatives:

    1) Use in all the layers of my application, including in the data source layer, BindingList<T> instead of IList<T>: How could I implement this? For example, the LINQ queries return IQueryable<T> which currently I’m converting to IList<T> by using ToList(). How could I convert the IQueryable<T> to BindingList<T>?

    2) Continuing using IList<T> in the data source, domain and service layers but converting the IList<T> to a BindingList<T> only in the presentation layer (in the views of the MVP pattern): What’s the best way to convert a IList<T> to a BindingList<T>? Since I have around 40 entities in my application do I need 1 class per entity or do I need only 1 generic class that could be used to make this conversion for each of the entities?

    Any other suggestions?

    Also, I tried this code to see if I could get a ‘simple’ solution to sort a any columns of my DataGridView but it didn’t worked.

    public class PriceBindingList: BindingList<PriceData>

    {

        public PriceBindingList(IList<PriceData> priceData):base(priceData)

        { }

    }

     

    ---

    HistPricesView.cs

     

      public partial class HistPricesViewForm : Form, IHistPricesView

      {

        // …..

        PriceBindingList histPricesBindingList;

     

        // Constructor

        public DailyPricesAndRetsOfAssetUserControl()

        {

          // ….

        }

     

     

        #region IHistPricesView Members

     

        public void SetHistPrices(IList<PriceData> histPrices)

        {

          histPricesBindingList = new PriceBindingList(histPrices);

          histPricesdataGridView.DataSource = histPricesBindingList;

      }

     

    ---

     

      public class PriceData

      {

        public DateTime Date { get; set; }

        public decimal OpenPrice { get; set; }

        public decimal HighPrice { get; set; }

        public decimal LowPrice { get; set; }

        public decimal ClosePrice { get; set; }

      public long Volume { get; set; }

      // ...............

    Should I use the code of the generic implementation of BindingList<T> that is mentioned in this link (http://msdn.microsoft.com/en-us/library/aa480736.aspx) or should I use a different one? I’m asking this because I saw several people recommending different code versions of BindingList<T> in the forums and I would prefer to use the faster and simplest version.

    My question touches in several subjects, including WinForms , but I think that the core issue is related to an architecture decision and for that reason I decided to include my question in this forum.

    EDIT: I don't know if this is relevant for this issue but I forget to mention that my DataGridView is a derived control that inherits from DataGridView in which I add the colums at run-time and associate them with the fields of the table of the database to which the DataGridView will be bound by using the following code that is called on the constructor of that control:

    this.AutoGenerateColumns = false;

    this.Columns.Add("Date", "Date");

    this.Columns["Date"].DataPropertyName = "Date"

    // code…

    Thanks. Best, Miguel.

    • Edited by Miguel T. _ Monday, August 30, 2010 2:35 PM Add some text in the title to make it clear
    Monday, August 30, 2010 1:35 AM

All replies

  • Just a few notes:

    1) The *automatic* sorting of a DataGridView only works with DataSets/DataTables. So it won't automatically sort if you change it from IList to IBindingList. However, there is a set of "standard" code available in some examples for getting a list to sort.

    2) I have an example of an n-tiered application that uses IBindingList here:

    http://www.insteptech.com/techLibrary/samplecode.htm

    Click one of the business object examples.

    Hope this helps.


    www.insteptech.com ; msmvps.com/blogs/deborahk
    We are volunteers and ask only that if we are able to help you, that you mark our reply as your answer. THANKS!
    Monday, August 30, 2010 2:16 AM
  • Hi Deborahk. The link that I include in my message includes code for a customized list that derives from BindingList<T> and in which the automatic sorting of DataGridView works. I have tested the code in the past and it worked. The question is that in that example I started with an empty BindinList and then I add data within a loop. Then I use DataGridView.DataSource and it worked. The question is that now I have different requirements since the starting point in not an empty list my a list that is the result of a query using LINQ to Objects or LINQ to SQL. Also, at that time when I tested BindingList, I used a simple application with no layers.

    The question is that I have already completed the domain model and data source layer of my application in which I used LINQ to Objects for queries in the domain layer and LINQ to SQL for queries in the data source layer. This means that my queries return IEnumerable<T> or IQueryable<T>. From these types it's easy to convert to IList<T> or List<T>. However, I think that I can't say the same for converting those types to DataTable or DataSet. Or, that would imply changing a lot of code in my application and if possible I realy would like to avoid that.

    Thanks for your feedback. I will take a look at your code.

    Best, Miguel.

    Monday, August 30, 2010 2:42 AM
  • Yes, OK. I misunderstood you.

    I thought you were using BindingList WITHOUT any extra code and the grid was sorting. The extra code I mentioned in my post is the code from the link you provided. So it sounds like you already have that covered.


    www.insteptech.com ; msmvps.com/blogs/deborahk
    We are volunteers and ask only that if we are able to help you, that you mark our reply as your answer. THANKS!
    Monday, August 30, 2010 3:30 AM
  • Hi DeborahK. Probably my message wasn’t I wasn't completely clear. In fact, for the example in this forum I used a BindingList<T> WITHOUT any extra code and it didn't work. However, I tried the BindingList<T> with the complete code from the link mentioned in a small example and I was able to sort the columns in the DataGridView. The question is that in that small example I started with an empty BindingList<T> and I added data within a loop. Now, I have different requirements since I'm using LINQ to Objects and LINQ to SQL and I will need to start with an IEnumerable<T> or IQueryable<T>. The question is that I don’t know how to convert IEnumerable<T> or IQueryable<T> to BindingList<T>.

    Since your last message I tried the following code and I was able to sort all the columns in my DataGridView (this is read-only data):

     //Using IQueryable<T>

    IQueryable<PriceData> histPrices = db.PriceData.Where(pd => (pd.AssetId == 310) &&

                                                                                                           (pd.Date >= startDate) &&

                                                                                                           (pd.Date <= endDate));

                                  

    dataGridView.DataSource = histPrices;

    If I use histPrices.AsEnumerable() I can also sort the columns in the DataGridView but if I use histPrices.ToList() I can’t. Based on this it looks that I could use IEnumerable<T> as the result of my queries and also in the methods of all the layers that need to handle with that data. Since my main requirement is to be able to sort columns in a DataGridView basically I need to know:

    1) If I only need to use read-only data should I use IEnumerable<T> as the result of my queries and in all the methods that deal with that data in the other layers?

    2) If I need two-way data binding should I use BindingList<T> instead? If yes, then how can I convert an IEnumerable<T> to a BindingList<T>? Or should I use another approach instead?

    Thanks for your feedback. Best, Miguel.

    Monday, August 30, 2010 2:25 PM
  • Hi Deborahk. In order to make the title more clear I change it from "IList<T> or BindingList<T> in the layers of N-Layer application?" to "IList<T>, IEnumerable<T> or BindingList<T> in the layers of N-Layer application using LINQ to SQL in the data source layer?".

    Best, Miguel.

    Monday, August 30, 2010 2:36 PM