C# LINQ、存储库模式和数据库抽象

C# LINQ、存储库模式和数据库抽象,c#,asp.net-mvc,linq,repository-pattern,C#,Asp.net Mvc,Linq,Repository Pattern,我现在花了一些时间来解决一个问题,而我至今还没有解决这个问题的办法。我有一个预定义的非常庞大的数据库,它的结构是固定的。我使用repository模式在服务代码和数据库逻辑之间创建一个抽象层。问题是,在将数据库对象从存储库中传递出去之前,我需要对其应用一些处理。因此,我不能直接使用Linq实体 基本上,存储库方法如下所示: public IList<Bookingcode> FindBookingcode(int id) { return (from b in _db.BOOK

我现在花了一些时间来解决一个问题,而我至今还没有解决这个问题的办法。我有一个预定义的非常庞大的数据库,它的结构是固定的。我使用repository模式在服务代码和数据库逻辑之间创建一个抽象层。问题是,在将数据库对象从存储库中传递出去之前,我需要对其应用一些处理。因此,我不能直接使用Linq实体

基本上,存储库方法如下所示:

public IList<Bookingcode> FindBookingcode(int id) {
   return (from b in _db.BOOKINGCODE
           where b.ID == id
           select new Bookingcode {
              Id = b.ID,
              Name = b.NAME.Trim()
           }).ToList();
}
public IList FindBookingcode(int-id){
返回(来自b in_db.BOOKINGCODE
其中b.ID==ID
选择新的预订代码{
Id=b.Id,
Name=b.Name.Trim()
}).ToList();
}
到目前为止,这个效果很好。但是我有很多对象,它们应该单独组成。 FindBookingcode()应该返回一个几乎完整的对象以及其他对象,如目录等。我现在的问题是,我必须多次重写映射,如本例所示:

public IList<Bookingcode> FindBookingcode(int id) {
    return (from b in _db.BOOKINGCODE
            join c1 in _db.CATALOG on b.CATALOGID equals c1.ID
            where b.ID == id
            let refs = (
                from bc1 in _db.BOOKINGCODE
                join p in _db.PACKAGE on bc1.ID equals p.BOOKINGCODE
                join bc2 in _db.BOOKINGCODE on p.PACKAGEREF equals bc2.ID
                join c in _db.CATALOG on bc.CATALOGID on bc2.CATALOGID equals c.ID
                where bc1.ID == b.ID
                select new PackageInfo {
                   ID = p.ID
                   BookingcodeRef = new Bookingcode { 
                       ID = bc2.ID,
                       Catalog = new Catalog { ID = c.ID }
                   }
                })
            select new Bookingcode {
              ID = b.ID,
              PackageInfo = refs.ToList()
            }).ToList();

}
public IList FindBookingcode(int-id){
返回(来自b in_db.BOOKINGCODE
在b.CATALOGID上的_db.CATALOG中加入c1等于c1.ID
其中b.ID==ID
让参考文献=(
来自bc1 in_db.BOOKINGCODE
将p加入bc1.ID上的_db.PACKAGE等于p.BOOKINGCODE
将bc2加入p.PACKAGEREF上的_db.BOOKINGCODE等于bc2.ID
在bc上的_db.CATALOG中加入c。在bc2上的CATALOGID.CATALOGID等于c.ID
其中bc1.ID==b.ID
选择new PackageInfo{
ID=p.ID
BookingcodeRef=新的Bookingcode{
ID=bc2.ID,
Catalog=新目录{ID=c.ID}
}
})
选择新的预订代码{
ID=b.ID,
PackageInfo=refs.ToList()
}).ToList();
}
我在存储库中还有一些L2O处理,用于组装返回的对象。还有一件事我没有很酷的解决方案,那就是告诉存储库它应该获取什么,比如FindBookingcode(id,includePackageInfo,includeCatalog)

以下是问题:

1) 这种做法完全愚蠢吗

2) 你能给我介绍一个使重新映射更简单的解决方案吗


3) 如何实现DDD的标准机制

您使用的是Linq到SQL还是实体框架

我假设您使用的是实体框架,正如您在问题中提到的“LINQ实体”。

您应该能够使用实体框架导航来进行这种映射 属性。您需要将导航属性添加到希望以这种方式映射的每个实体。这就像告诉可视化设计器哪个属性映射到另一个实体中的对应属性一样简单


请参阅,以获取非常快速的入门指南。我建议观看整个系列,因为它们信息量很大。

在我的存储库中,我有一个单独的构建方法,它接受LINQ to SQL实体并返回一个业务对象

build方法类似于(this.Container是Unity IoC容器,在本例中并不重要):


这是通过从数据库中获取每个LINQ to SQL实体并通过构建方法运行它来实现的,因此在这种情况下,您的结果将是业务对象的可枚举性,而不是LINQ to SQL实体。

如果我调用存储库方法,如
var list = x.FindBookingcode(int id)
我希望能够将项目添加到列表中,而不必担心如何将其持久化到数据库中。在示例实现中,您的存储库函数无法检测到有人向列表中添加了某些内容,因此无法对其执行任何操作


我也希望能够通过规范。规范基本上是对存储库类型执行操作的委托,返回一个布尔值,以指示查询是否必须考虑它。通常,您会实现一个实现逻辑and、or和not运算符的基本规范,这样您就可以轻松地将规范组合成新的规范。

首先-sry对于我的答案,我很长一段时间都很忙,以至于忘了回答

John,你的解决方案很好地解决了我的多重重映射问题

DoctaJonez,我正在使用Linq2SQL。我用实体框架做了一些测试,也用NHibernate做了一些测试。映射问题的根源是,我有一个给定的数据库模式,它有时真的很难看。因此,在访问数据时,我有很多处理工作要做。NHibernate工作得很好,我想我会在不久的将来将其添加到项目中

汉斯,你的观点很对。但是,由于该项目只是数据库的查询api,因此不会写入数据库。它更像是一个带有服务的dll,其他应用程序使用它从我公司使用的预订软件中获取信息

您提到了“规格”,这也是一个很好的观点。因为我有很多过滤器的巨大搜索查询,所以我真的需要一个好的存储库api。这样做的问题是,例如,过滤器的不同组合也会启动不同的处理逻辑。这也应该创建不同的SQL来提高效率

因为我已经映射了对象,并且使用Linq到SQL,所以我无法让规范像它们应该的那样工作。因此,我在存储库中有很多方法来获取具有不同条件的对象,如下所示:

Bookingcode FindBookingcode(int id);
Bookingcode FindBookingcode(string code, string catalog);
List<Bookingcode> FindBookingcode();
List<Bookingcode> FindBookingcode(int[] ids);
List<Bookingcode> FindBookingcode(string code);
List<Bookingcode> FindBookingcode(string[] codes);
List<Bookingcode> FindBookingcodes(Catalog catalog);
对于更大的界面,如搜索,我使用过滤对象,如

srv.SearchTransactions(new TransactionSearchFilter { 
    Customer = 1234, Destination = "DXB", ExtractServices = true });
然后,存储库有一些逻辑来从数据库中取出这些内容。在存储库中,我正在进行测试,以使某些东西能够像这样工作

    repo.QueryTransactions()
    .Include<Customer>()
    .Include<TransactionsService>()
    .FilterBy(TransactionSearchFilter.Customer, 1234)
    .FilterBy(TransactionSearchFilter.Destination, "DXB")
    .Execute();
repo.QueryTransactions()
.包括()
.包括()
.FilterBy(TransactionSearchFilter.Customer,1234)
.FilterBy(交易)
repo.GetBookingcodes().WithCatalog("WI09").WithCode("XYZ10001");
srv.SearchTransactions(new TransactionSearchFilter { 
    Customer = 1234, Destination = "DXB", ExtractServices = true });
    repo.QueryTransactions()
    .Include<Customer>()
    .Include<TransactionsService>()
    .FilterBy(TransactionSearchFilter.Customer, 1234)
    .FilterBy(TransactionSearchFilter.Destination, "DXB")
    .Execute();