15

在设置我的 DataContext 以便在我的扩展 LinqToSql 类中轻松访问方面的最佳实践是什么?

例如,我的 dbml 中有一个“用户”实体,我想向该类添加方法,如下所示:

Partial Public Class User

    Public Function GetUser(ByVal UserID as Integer) as User
         'Do Work
    End Function

End Class

为了访问我的 DataContext 我必须在方法中声明它,如下所示:

Partial Public Class User

    Public Function GetUser(ByVal UserID as Integer) as User
         Dim dc as New MyDataContext()
         Return (From u in dc.Users Where u.ID = UserID).Single()
    End Function

End Class

我不想对每种方法都这样做。通常(如果我没有扩展 LinqToSql dbml 类)我可以这样做:

Partial Public Class User
    Private dc as MyDataContext

    Public Sub New()
         dc = new MyDataContext()
    End Sub

    Public Function GetUser(ByVal UserID as Integer) as User
         Return (From u in dc.Users Where u.ID = UserID).Single()
    End Function

    Public Function GetAllUsers() as IEnumerable(Of User)
         Return From u in dc.Users
    End Function

    'etc...

End Class

这将允许我访问每个方法的数据上下文,而不必每次都重新声明它。但是你当然不能这样做,因为 dbml 已经有一个构造函数。如果有任何变化,将代码添加到 dbml 中总是会被覆盖。

有人对如何在这里为自己节省一些多余的代码有什么好主意吗?

蒂亚!

4

5 回答 5

15

首先,确保您在完成后处理您的 DataContext!他可能是一个沉重的小混蛋(编辑实例化不重,但如果您继续使用它而不处置它,则很重);您不希望旧的 DataContexts 在内存中徘徊。

其次,DataContext 旨在表示单个逻辑事务。例如,您应该在每次要开始新事务时创建一个新事务,并在事务完成时将其删除。因此,出于您的目的,这可能是该GetUser方法的范围。如果您有一系列需要作为一个组进行的 DB 调用,则在摆脱它之前,它们都应该使用相同的 DC。

于 2009-02-14T17:27:40.580 回答
13

正如Rex M 所说,数据上下文旨在为每个逻辑事务实例化、使用和处置。像这样的模式有时被称为“工作单元”。

最常见的方法(据我所知)是在 using 块中实例化您的数据上下文。我有一段时间没有使用 VB,但它应该看起来像这样:

Using dc As New MyDataContext()
   user = (From u in dc.Users Where u.ID = UserID).Single()
End Using

这不仅增强了事务/工作单元的外观(通过代码的物理形状),而且确保在块结束时在数据上下文中调用 Dispose()。

请参阅此 MSDN 页面

通常,DataContext 实例旨在持续一个“工作单元”,但是您的应用程序定义了该术语。DataContext 是轻量级的,创建起来并不昂贵。典型的 LINQ to SQL 应用程序在方法范围内创建 DataContext 实例,或者将其作为表示一组相关数据库操作的逻辑集的短期类的成员。

于 2009-02-14T17:44:42.570 回答
0

我认为也许真正的问题User可能不是实例成员调用的正确位置GetUser

于 2009-02-14T17:29:42.463 回答
0

我认为有几种不同的方法可以解决这个问题,这将是很好的做法。首先,您可以使用存储库模式,在其中查询存储库以获取对象,然后将其发送到数据库,检索对象-可能将其与数据上下文分离或根据存储库的实现保留数据上下文-并将其退还给您。您的对象的工厂方法将位于存储库上,而不是实体本身。您可能会使用反射和泛型来最小化您必须实现的方法数量并保持代码干燥。

另一种方式,以及 LINQtoSQL 旨在本地使用的方式恕我直言,是为您打算执行的每组数据库操作创建数据上下文。在这种情况下,数据上下文的创建也发生在实体之外,通常在使用实体的类中,而不是在数据层中。您还可以向数据上下文添加方法——使您的实际数据上下文抽象并从中继承——再次使用反射来执行一些常见的检索功能,这样您就不必重复它们了。您可能必须使用像 ActiveRecords 这样的数据库模式,其中 id 列始终具有相同的名称才能使其工作。

另一方面,您可以考虑使用nHibernate或 Castle 的ActiveRecord,而不是在您自己的解决方案中复制上述任何一个。

于 2009-02-14T17:49:42.370 回答
0

如果您不理会 User 类并允许 IDE 处理它的创建,这可能会更容易。

通常我更喜欢让一个单独的类来处理数据检索。假设您将其称为 UserDataProvider 并且所有获取 User 实例的调用最终都会通过此类。

UserDataProvider 的构造函数可以实例化数据上下文对象的全局实例以供重用。它看起来像这样(在 C# 和未经测试的代码中,请耐心等待):

public class UserDataProvider 
{
    private UserDataContext _data = null;

    public UserDataProvider()
    {
        _data = new UserDataContext();
    }

    public User GetUser(int userID)
    {
        return _data.Users.FirstOrDefault(u => u.UserID == userID);
    }
}

或者,您可以将初始化放在一个属性中并访问该属性以使用数据上下文。

public class UserDataProvider 
{
    private UserDataContext _dataContext;

    private UserDataContext DataContext 
    {
        get
        {
            if (_data == null)
                _data = new UserDataContext();

            return _data;
        }
    }

    public User GetUser(int userID)
    {
        return DataContext.Users.FirstOrDefault(u => u.UserID == userID);
    }
}
于 2009-02-14T18:28:35.427 回答