在C#应用程序中使用LINQ到SQL的最佳实践方式是什么?[设计模式]

在C#应用程序中使用LINQ到SQL的最佳实践方式是什么?[设计模式],c#,.net,linq-to-sql,design-patterns,C#,.net,Linq To Sql,Design Patterns,好吧,我一直在努力改进我的编码方式,因为这是我的激情所在。我有一个.dbml文件(),我用它来访问我的数据库 想象一下,如果您愿意的话,您的数据库中有一个Person表,您希望提供一种删除、添加和修改Person记录的方法 我目前处理事情的方式是创建名为PersonRepository、CarRepository、DocumentRepository等的类。对于数据库中的每个表,我创建一个repository类 public List<Person> GetPeopleFromDOB

好吧,我一直在努力改进我的编码方式,因为这是我的激情所在。我有一个.dbml文件(),我用它来访问我的数据库

想象一下,如果您愿意的话,您的数据库中有一个Person表,您希望提供一种删除、添加和修改Person记录的方法

我目前处理事情的方式是创建名为PersonRepository、CarRepository、DocumentRepository等的类。对于数据库中的每个表,我创建一个repository类

public List<Person> GetPeopleFromDOB(DateTime x, DateTime y)
{
    // Do the logic here.
}
这些存储库类通常由以下类似内容组成:

MyDatabaseContext db = new MyDatabaseContext();

public Person GetPersonByID(int id)
{
    return db.Person.Where(p => p.ID == id);
}
每个表的基本CRUD功能几乎相同

如果我需要更具体的东西,例如“塞尔吉奥,我需要一份出生在x和y之间的所有人的名单”;然后我只是将该方法添加到PersonRepository类中

public List<Person> GetPeopleFromDOB(DateTime x, DateTime y)
{
    // Do the logic here.
}
公共列表GetPeopleFromDOB(日期时间x,日期时间y) { //按这里的逻辑做。 } 我的另一个想法是创建一个DataAccess.cs类,将所有这些方法都放在其中(我们将讨论现有的每个表4-5个方法),并将它们按区域划分


更有知识的程序员在做什么?对于一个热情的年轻程序员(我今年20岁),您会提供什么建议?

以下是您在做上述工作时遇到的问题:

在应该使用IQueryable时使用列表

Namespace Data

#Region "Interface"
    Public Interface IUserService
        Function GetAllUsers() As IList(Of User)
        Function GetUserByID(ByVal id As Integer) As User
    End Interface
#End Region


#Region "Service"
    Public Class UserService : Implements IUserService

        Private _ValidationDictionary As IValidationDictionary
        Private _UserRepository As IUserRepository

        Public Sub New(ByVal validationDictionary As IValidationDictionary, ByVal UserRepository As IUserRepository)
            _ValidationDictionary = validationDictionary
            _UserRepository = UserRepository
        End Sub

        Public Function GetAllUsers() As System.Collections.Generic.IList(Of User) Implements IUserService.GetAllUsers
            Return _UserRepository.GetAllUsers
        End Function


        Public Function GetUserByID(ByVal id As Integer) As User Implements IUserService.GetUserByID
            Return _UserRepository.GetUserByID(id)
        End Function

    End Class
#End Region
End Namespace

基本上,在需要数据之前,永远不应该获取数据。使用这种方法,您总是从数据库中获取数据,随后的LINQ查询将对所有数据起作用。为什么不建立查询,让LINQ细化到只在您需要的时候得到您需要的东西呢

在扩展方法完美时使用方法

您正在使用GetPeopleFromDOB之类的东西创建一个实用类方法。为什么不把它作为一种扩展方法呢?如果你让它们都返回IQueryable,你也可以连续使用它们。例如,
GetPeople().StatusEnabled().BornInJuly().age大于(57)同时,如果必须这样做,至少考虑在部分类或静态实用程序类中这样做。

考虑使用ActiveRecord/Repository模式作为根目录

现在您正在创建几个硬编码的存储库,但您应该将它们建立在存储库的基础上吗

为什么不使用验证器?

如果您使用的是ASP.NET MVC,验证是必不可少的,但是对于webforms,您也可以使用数据注释验证程序

我会坚持使用并坚持使用您的存储库类。如果您的数据库随着时间的推移而增长,想象一下DataAccess类会变得多大。你会暂时摆脱它,但它会不断增长,以至于你在一个类中有数千行代码(我以前在这样的类中见过15000多行代码),而你被卡住了

您需要使用一个存储库来使用L2S直接连接到您的DBML

然后,您需要创建一个与存储库对话的服务

最后,您将在您或您的MVC控制器中使用该服务

用户存储库

Namespace Data

#Region "Interface"
    Public Interface IUserRepository
        Function GetAllUsers() As IList(Of User)
        Function GetUserByID(ByVal id As Integer) As User
    End Interface
#End Region

#Region "Repository"
    Public Class UserRepository : Implements IUserRepository
        Private dc As MyDataContext
        Public Sub New()
            dc = New MyDataContext
        End Sub

        Public Function GetAllUsers() As System.Collections.Generic.IList(Of User) Implements IUserRepository.GetAllUsers
            Dim users = From u In dc.Users
                        Select u
            Return users.ToList
        End Function

        Public Function GetUserByID(ByVal id As Integer) As User Implements IUserRepository.GetUserByID
            Dim viewUser = (From u In dc.Users
                       Where u.ID = id
                       Select u).FirstOrDefault
            Return viewUser
        End Function

    End Class
#End Region
End Namespace
用户服务

Namespace Data

#Region "Interface"
    Public Interface IUserService
        Function GetAllUsers() As IList(Of User)
        Function GetUserByID(ByVal id As Integer) As User
    End Interface
#End Region


#Region "Service"
    Public Class UserService : Implements IUserService

        Private _ValidationDictionary As IValidationDictionary
        Private _UserRepository As IUserRepository

        Public Sub New(ByVal validationDictionary As IValidationDictionary, ByVal UserRepository As IUserRepository)
            _ValidationDictionary = validationDictionary
            _UserRepository = UserRepository
        End Sub

        Public Function GetAllUsers() As System.Collections.Generic.IList(Of User) Implements IUserService.GetAllUsers
            Return _UserRepository.GetAllUsers
        End Function


        Public Function GetUserByID(ByVal id As Integer) As User Implements IUserService.GetUserByID
            Return _UserRepository.GetUserByID(id)
        End Function

    End Class
#End Region
End Namespace
现在只需确保像上面提到的那样使用


还有,请原谅我的错误。您可能需要通过代码转换器运行它才能获得C语言的东西。

哦,天哪。15,000? 我为那个不得不维护这一点的家伙感到抱歉。(编辑:这是针对Windows窗体应用程序的)感谢这些链接。IQueryable过滤数据库中的内容,而List过滤内存中的内容。我得弄清楚哪个对我最好。另外,您是否有关于如何在此上下文中使用扩展方法的有用链接?我坚持使用IQueryable。如果您确实希望/需要在内存中执行查询,那么只需在存储库方法调用的结果上添加.ToList(),然后进行筛选。(编辑:这里有一个制作“流畅”的链接)L2S扩展方法。在这里,请注意它们有IQueryable:我指出这一点是因为这是一个将扩展方法与LINQ to SQL结合使用的好例子,并且还强调了cavaets。使用ActiveRecord模式给我带来了什么好处?我觉得它在不需要的地方增加了复杂性。如果我使用这种SingleRepository方法,则添加了funct独立性要容易得多,代码会导致调用“PersonRepository.FindPeople(),.FindPerson(),FindWomen(),FindMen()等”更自然它将数据访问一般化,并在DAL/BLL之间创建一致性。此外,它将数据访问抽象出来,并允许您轻松地将底层数据层切换到另一种技术,如实体框架或NHibernate。我不理解您在这里提供服务的目的。您似乎只是在包装存储库方法没有实际添加任何值的ds。验证字典做什么?您是否有一个链接可以共享以解释有关此模式的更多信息?谢谢。