您的位置:知识库 » 数据库

在LINQ to SQL中使用Translate方法以及修改查询用SQL

作者: Jeffrey Zhao  来源: 博客园  发布时间: 2008-09-20 23:37  阅读: 6357 次  推荐: 0   原文链接   [收藏]  
摘要:老赵在最近的项目中使用了LINQ to SQL作为数据层的基础,在LINQ to SQL开发方面积累了一定经验,也总结出了一些官方文档上并未提及的有用做法,特此和大家分享。
[1] 引入
[2] 使用Translate方法1
[3] 使用Translate方法2
[4] 改变LINQ to SQL所执行的SQL语句
[5] 扩展所受的限制

 

使用Translate方法

幸亏DataContext提供了Translate方法,Translate方法的作用就是从一个DbDataReader对象中生成一系列的实例。其中最重要的就是一个带范型的重载:

public static List<Item> GetItemsForListing(int ownerId)
{
    ItemDataContext dataContext = new ItemDataContext();
    dataContext.Connection.Open();

    SqlCommand command = new SqlCommand(
        "SELECT [ItemID], [Title], [UserID], [CreateTime]" +
        " FROM [Item] WHERE [UserID] = " + ownerId +
        " ORDER BY [CreateTime]",
        (SqlConnection)dataContext.Connection);

    using (DbDataReader reader = command.ExecuteReader
                         (CommandBehavior.CloseConnection))
    {
        return dataContext.Translate<Item>(reader).ToList();
    }
}

在这段代码里,我们拼接出了一段SQL语句,实现了我们需要的逻辑。在ExecuteReader之后即使用dataContext.Translate方法将DbDataReader里的数据转换成Item对象。使用Translate方法除了方便之外,生成的对象也会自动Attach到DataContext中,也就是说,我们可以继续对获得的对象进行操作,例如访问Item对象的Comments属性时会自动去数据库获取数据,改变对象属性之后调用SubmitChange也能将修改提交至数据库。Translate方法从DbDataReader中生成对象的规则和内置的DataContext.ExecuteQuery方法一样,大家可以查看MSDN中的说明(中文英文)。

此外,这里有两个细节值得一提:

  • 为什么调用ExecuteReader方法时要传入CommandBehavior.CloseConnection:LINQ to SQL中的DataContext对象有个特点,如果在使用时它的Connection对象被“显式”地打开了,即使调用了DataContext对象的Dispose方法也不会自动关闭。因此我们在开发程序的时候一定要注意这一点。例如,在调用ExecuteReader是传入CommandBehavior.CloseConnection,这样就保证了在关闭DbDataReader时同时关闭Connection——当然,我们也可以不这么做。
  • 在调用Translate方法后为什么要直接调用ToList方法:因为GetItemsForListing方法的返回值是List<Item>,这是原因之一。另一个原因是Translate方法并不会直接生成所有的对象,而是在外部代码访问Translate方法返回的IEnmuerable<T>时才会生成其中每个对象。这也是一种Lasy Load,但是也导致了所有的对象必须在Reader对象关闭之前生成,所以我一般都会在Translate方法后直接调用ToList方法,保证所有的对象已经生成了。虽然事实上我们也可以不使用using关键字而直接返回Translate方法生成的IEnumerable<Item>,不过这么做的话当前链接就得不到释放(释放,而不是关闭),也就是把处理数据连接的问题交给了方法的使用者——很可能就是业务逻辑层。为了确保分层结构的职责分明,我一般倾向于在这里确保所有对象的已经生成了。

上面的例子使用拼接SQL字符串的方式来访问数据库,那我们又该如何使用LINQ to SQL呢?幸亏LINQ to SQL中的DataContext提供了GetCommand方法。我们直接来看一个完整的扩展:

public static class DataContextExtensions
{
    public static List<T> ExecuteQuery<T>
        (this DataContext dataContext, IQueryable query)
    {
        DbCommand command = dataContext.GetCommand(query);
        dataContext.OpenConnection();

        using (DbDataReader reader = command.ExecuteReader())
        {
            return dataContext.Translate<T>(reader).ToList();
        }
    }

    private static void OpenConnection
        (this DataContext dataContext)
    {
        if (dataContext.Connection.State == 
            ConnectionState.Closed)
        {
            dataContext.Connection.Open();
        }
    }
}

自从有了C# 3.0中的Extension Method,很多扩展都会显得非常优雅,我非常喜欢这个特性。DataContextExtensions是我对于LINQ to SQL中DataContext对象的扩展,如果以后有新的扩展也会写在这个类中。OpenConnection方法用于打开DataContext中的数据连接,今后的例子中也会经常看到这个方法。而这次扩展的关键在于新的ExecuteQuery方法,它接受一个IQueryable类型的对象作为参数,返回一个范型的List。方法中会使用DataContext的GetCommand方法来获得一个DbCommand。在我之前的文章,以及MSDN中的示例都只是通过这个DbCommand对象来查看LINQ to SQL所生成的查询语句。也就是说以前我们用它进行Trace和Log,而我们这次将要真正地执行这个DbCommand了。剩下的自不必说,调用ExecuteReader方法获得一个DbDataReader对象,再通过Translate方法生成一个对象列表。

0
0
标签:LINQ to SQL

数据库热门文章

    数据库最新文章

      最新新闻

        热门新闻