3

我现在花了一些时间来解决一个到目前为止我还没有解决方案的问题。我有一个预定义的非常庞大的数据库,其结构是固定的。我使用存储库模式在服务代码和数据库逻辑之间创建一个抽象层。问题是,我需要对数据库对象进行一些处理,然后再将它们传递出存储库。因此我不能直接使用 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();
}

到目前为止,这工作得很好。但是我有很多应该单独组合的对象。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();

}

我还在存储库中进行了一些 L2O 处理,用于组装返回的对象。另一件事我没有很酷的解决方案,是一种告诉存储库它应该获取什么的方法,例如 FindBookingcode(id, includePackageInfo, includeCatalog)。

所以这里有问题:

1)这种方法完全愚蠢吗?

2)你能指导我找到一个使重新映射更简单的解决方案吗?

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

4

4 回答 4

3

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

build 方法看起来像(this.Container 是一个 Unity IoC 容器,对于示例并不重要):

private IGroup BuildGroup(Entities.Group group)
{
    IGroup result = this.Container.Resolve<IGroup>();
    result.ID = group.GroupID;
    result.Name = group.Name;

    return result;
}

然后每个方法使用 build 方法返回一个业务对象:

public override IGroup GetByID(int id)
{
    try
    {
        return (from g in this.Context.Groups
                where g.GroupID == id && g.ActiveFlag
                select this.BuildGroup(g)).Single();
    }
    catch (InvalidOperationException)
    {
        return null;
    }
}

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

于 2009-06-26T16:13:25.030 回答
1

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

我在这里假设您使用的是实体框架,因为您在问题中提到了“LINQ 实体”。

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

观看How do I Entity Framework 视频系列以获得非常快速的入门指南。我建议观看整个系列,因为它们提供的信息非常丰富。

于 2009-06-26T16:07:10.567 回答
1

如果我调用类似的存储库方法

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

我也希望能够通过规范。规范基本上是作用于您的存储库类型的委托,返回一个布尔值以指示是否必须考虑查询。通常,您将实现一个基本规范,该规范实现了逻辑与或与非运算符,以便您可以轻松地将规范组合成新的规范。

于 2009-06-26T16:37:08.673 回答
0

首先-sry 很长一段时间我的回答^^ 我只是太忙了,我忘了回答。

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

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

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

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

因为我已经映射了对象并使用 Linq to SQL,所以我无法像应有的那样使规范工作。所以我在存储库上有很多方法来获取具有不同 crierias 的对象,如下所示:

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);

因为我没有使用 IQueryable 我不能像

repo.GetBookingcodes().WithCatalog("WI09").WithCode("XYZ10001");

对于像 Searches 这样的较大界面,我使用像这样的过滤器对象

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();

它在内部构建了一个标准/规范。但这真的看起来像实体框架,也许如果我更深入那里,我可以使用它或 NHibernate。

我的存储库中最有问题的部分是搜索,因为需要在性能方面创建某种动态 SQL。我玩过 PredicateBuilder 但如果设置了特定的过滤器,我无法解决一些我更改/包含表连接的查询。

我想我必须“扫描”更多文档。感谢您的回复。

于 2009-12-29T17:06:55.730 回答