【问题标题】:LinqToSql declare and instantiate DataContext best practice?LinqToSql 声明和实例化 DataContext 最佳实践?
【发布时间】:2010-10-07 15:45:12
【问题描述】:

在设置我的 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 中总是会被覆盖。

有人对如何在这里节省一些多余的代码有什么好的想法吗?

TIA!

【问题讨论】:

    标签: .net vb.net linq-to-sql datacontext


    【解决方案1】:

    如果您不理会 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);
        }
    }
    

    【讨论】:

      【解决方案2】:

      首先,确保在完成后处理 DataContext!他可能是个笨重的小混蛋(edit 实例化并不笨重,但如果你继续使用它而不丢弃它,那么它就很笨重);您不希望旧的 DataContexts 在内存中徘徊。

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

      【讨论】:

      • 数据上下文本身实际上非常轻量级,尽管它可能会引用很多实体。处理它以释放实体是一个非常好的主意。如果它是一个重量级的对象,我会更倾向于保留它,这样我就不必重新创建它。
      • @tvanfosson 这就是我的意思;编辑以使这一点更清楚。 DC 可能会带来很大的负担。最好尽快摆脱它。
      • 我实际上更喜欢使用 using 语句,主要是因为我认为它增加了可读性。只是想添加一些其他参数。
      • More grist 到工厂...
      【解决方案3】:

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

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

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

      【讨论】:

        【解决方案4】:

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

        执行此操作的最常见方法(据我所知)是在 using 块中实例化您的数据上下文。好久没用VB了,不过应该是这样的:

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

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

        this MSDN page

        一般来说,一个 DataContext 实例被设计为持续一个“单元 工作”,但是您的应用程序定义 那个词。一个 DataContext 是 轻巧且不昂贵 创建。一个典型的 LINQ to SQL 应用程序创建 DataContext 方法范围内的实例或作为 短期课程的成员 表示一组相关的逻辑 数据库操作。

        【讨论】:

          【解决方案5】:

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

          【讨论】:

          • 你这是什么意思?你能进一步解释一下吗?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-07-19
          • 2013-11-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多