从传统数据库访问转向LINQ过程中遇到的一些问题和解决方法

来源:互联网 发布:js 页面加载动画 编辑:程序博客网 时间:2024/05/20 10:22

最近在将一个原来用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;
        }
    }

原创粉丝点击