從傳統數據庫訪問轉向LINQ過程中遇到的一些問題和解決方法

最近在將一個原來用ASP.NET2.0設計的網站遷移到NET3.5上,主要是要將數據訪問從傳統的數據庫訪問方式轉換爲LINQ技術。其間也遇到一些問題,這裏是一些典型的問題。

我原來的項目是在NET2.0下用VS2005開發的,現在使用VS2008了。

 1  web.config的問題

由於原來的系統是在NET2.0下用VS2005開發的,在web.config中的有大量對2.0的引用。如果用VS2008直接打開VS2005的網站工程,VS會把這個網站作爲aps.net2.0的項目處理。LINQ這些3.5的新功能都不能使用。

解決方法:我用的是笨辦法,直接用VS2008新建一個網站,然後把原來網站的web.config中的配置逐行拷貝到新站點的配置文件中。

2 頁面上的數據源

這是引入LINQ最好的地方了。原本頁面上諸多控件都是綁定到SQLDataSource上的。現在改爲綁定到ObjectDataSource數據源上了。這樣將頁面邏輯和數據訪問徹底分離了。我喜歡將ObjectDataSource數據源的返回結果都定義爲List<T>類型的。

3 GridView控件的數據過濾

SQLDataSource返回的是DataSet,DataTable類型,這種類型可以支持GridView的過濾。程序中只要通過代碼動態設置過濾條件,GridView會自動完成過濾。

原來的過濾代碼大體如下

aspx文件:

<tr>
                                        <td align="right">
                                            產品類別:
                                        </td>
                                        <td>
                                            <asp:DropDownList ID="DropDownListProductList" runat="server" DataSourceID="SqlDataSourceTypes"
                                                DataTextField="ProductTypeName" DataValueField="ProductTypeID" Width="130px" AutoPostBack="True" OnSelectedIndexChanged="DropDownListProductList_SelectedIndexChanged">
                                            </asp:DropDownList>&nbsp;
                                        </td>
                                    </tr>
                                    <tr>
                                        <td align="right">
                                            產品代碼:</td>
                                        <td >
                                            <asp:TextBox ID="TextBoxProductTypeCode" runat="server" Width="50px" ReadOnly="true"/>-<asp:TextBox ID="TextBoxProductCode" runat="server" Width="50px"/>
                                        </td>
                                    </tr>

    <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:DBConnectionString %>"
        SelectCommand="SELECT [ProductTypeName], [ProductTypeCode], [ProductTypeID] FROM [tbl_ProductType] WHERE len([ProductTypeCode])=2 ">
    </asp:SqlDataSource>
    <asp:SqlDataSource ID="SqlDataSourceTypes" runat="server" ConnectionString="<%$ ConnectionStrings:DBConnectionString %>"
    SelectCommand="SELECT [ProductTypeName], [ProductTypeCode], [ProductTypeID] FROM [tbl_ProductType] WHERE len([ProductTypeCode])=4 "
      >
    </asp:SqlDataSource>

cs文件:

       protected void DropDownListProductTopType_SelectedIndexChanged(object sender, EventArgs e)
    {
        if (-1 < DropDownListProductTopType.SelectedIndex)
        {
            this.SqlDataSourceTypes.FilterExpression = string.Format("[ProductTypeCode] LIKE '{0}%'", DropDownListProductTopType.SelectedValue.ToString().Trim());
            this.DropDownListProductList.DataBind();
            SetProductTypeCode();
        }
    }

GridView只能支持對DataSet,DataTable的過濾,不支持對List<T>的過濾。

解決方法:

1 )將數據源的返回類型改爲DataTable類型的,MS給出的例子就是這樣的。

2 )如果和我一樣不喜歡DataTable,就需要修改數據獲取方法了。

將過濾條件作爲參數,如下面GetProductTypes的category參數就是過濾條件。

public static List<DAO.ProductTypeInfo> GetProductTypes(string category)

這種方法的缺點是過濾條件是固定的,不夠靈活。

如果需要一個靈活的過濾機制,還是考慮第一種方法把。

遷移後的代碼:

aspx文件:

<tr>
                                        <td align="right">
                                            產品類別:
                                        </td>
                                        <td>
                                            <asp:DropDownList ID="DropDownListProductList" runat="server" DataSourceID="ObjectDataSource_ProductTypes"
                                                DataTextField="ProductTypeName" DataValueField="ProductTypeID"
                                                Width="130px" AutoPostBack="True"
                                                OnSelectedIndexChanged="DropDownListProductList_SelectedIndexChanged">
                                            </asp:DropDownList>&nbsp;
                                        </td>
                                    </tr>
                                    <tr>
                                        <td align="right">
                                            產品代碼:</td>
                                        <td >
                                            <asp:TextBox ID="TextBoxProductTypeCode" runat="server" Width="50px" ReadOnly="true"/>-<asp:TextBox ID="TextBoxProductCode" runat="server" Width="50px"/>
                                        </td>
                                    </tr>

  <asp:ObjectDataSource ID="ObjectDataSource_ProductTypes" runat="server"
                                SelectMethod="GetProductTypes" TypeName="SystemBL">
          <SelectParameters>
              <asp:ControlParameter ControlID="DropDownListProductTopType" Name="category" PropertyName="SelectedValue"
                Type="String" />
            </SelectParameters>                     
    </asp:ObjectDataSource>   
                           
    <asp:ObjectDataSource ID="ObjectDataSource_ProductCategories" runat="server"
                                SelectMethod="GetProductCategories" TypeName="SystemBL">
                            </asp:ObjectDataSource>                                             

cs文件:

     public static List<DAO.ProductTypeInfo> GetProductTypes(string category)
    {
        if (null == ProductTypList)
        {
            ProductTypList = new List<DAO.ProductTypeInfo>();
            using (DAO.SystemDataDataContext db = new DAO.SystemDataDataContext(PublicDefine.SQLConnectString))
            {
                foreach (DAO.ProductTypeInfo type in db.ProductTypeInfos)
                {
                    if (4 == type.ProductTypeCode.Trim().Length)
                    {
                        ProductTypList.Add(type);
                    }
                }
            }           
        }
        //filter
        List<DAO.ProductTypeInfo> list;
        if (string.Empty == category)
        {
            list = ProductTypList.ToList<DAO.ProductTypeInfo>();
        }
        else
        {
            list = new List<DAO.ProductTypeInfo>();
            int len=category.Trim().Length;
            foreach (DAO.ProductTypeInfo type in ProductTypList)
            {
                if (category.Trim() == type.ProductTypeCode.Substring(0, len))
                {
                    list.Add(type);
                }
            }
        }
        //sort
        list.Sort(CompareProductType);
        return list;
    }

4 GridView控件的自動排序

GridView控件的自動排序也是非常有用的功能。但遺憾的是隻能支持DataAset,DataTable類型。

解決方法:

需要截獲sorting事件,然後中止GridView的自動處理,自己調用數據獲取方法來進行過濾。由於需要過濾的數據列比較多,這裏還需要引入LINQ的動態查詢庫。

LINQ的動態庫是微軟提供的一個LINQ Dynamic Query library. 可以從C# Dynamic Query Library (included in the /LinqSamples/DynamicQuery directory) 下載。

aspx:

    <asp:ObjectDataSource ID="ObjectDataSource_Products" runat="server"
        SelectMethod="GetProductsView" TypeName="SystemBL">
        <SelectParameters>
            <asp:ControlParameter ControlID="DrpProductTypeList" DefaultValue="-1"
                Name="type" PropertyName="SelectedValue" Type="Int32" />
            <asp:Parameter DefaultValue="" Name="orderby"  Type="String" />
        </SelectParameters>
    </asp:ObjectDataSource>

頁面邏輯cs

protected void GridViewProductsList_Sorting(object sender, GridViewSortEventArgs e)
    {

        //取得過濾列,然後設置ObjectDataSource的對應參數
        ObjectDataSource_Products.SelectParameters["orderby"].DefaultValue = e.SortExpression;

       //重新獲取數據
        GridViewProductsList.DataBind();

       //中止GridView的過濾
        e.Cancel = true;       
    }

5 LINQ動態查詢

在使用了LINQ的動態查詢庫之後,動態查詢就和原來動態拼裝SQL語句一樣容易了。

using System.Linq.Dynamic;

....

public static List<DAO.ProductViewInfo> GetProductsView(int type,string orderby)
    {
        string orderexpress;
        if (null == orderby || string.Empty == orderby)
        {
            orderexpress = "ProductCode";
        }
        else
        {
            orderexpress = orderby;
        }

        using (DAO.SystemDataDataContext db = new DAO.SystemDataDataContext(PublicDefine.SQLConnectString))
        {
            List<DAO.ProductViewInfo> products;
            if (type > 0)
            {
                var result = from p in db.ProductViewInfos
                           where p.ProductTypeID == type
                             orderby (orderexpress)
                           select p;
                products = result.ToList<DAO.ProductViewInfo>();
            }
            else
            {
                var query = db.ProductViewInfos
                            .OrderBy(orderexpress);

                products = query.ToList<DAO.ProductViewInfo>();
            }
            return products;
        }
    }

發佈了71 篇原創文章 · 獲贊 0 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章