[英]Where do objects merge/join data in a 3-tier model?
Its probarbly a simple 3-tier problem. 它可能是一个简单的3层问题。 I just want to make sure we use the best practice for this and I am not that familiary with the structures yet.
我只是想确保我们为此使用最佳实践,而我对结构并不那么熟悉。
We have the 3 tiers: 我们分为三层:
Lets think of setup where we have a database of [Persons]. 让我们考虑一下我们有[Persons]数据库的地方的设置。 They can all have multiple [Address]es and we have a complete list of all [PostalCode] and corresponding citynames etc.
他们都可以有多个[Address],并且我们具有所有[PostalCode]和相应城市名称的完整列表。
The deal is that we have joined a lot of details from other tables. 要做的是,我们从其他表中加入了许多细节。
{Relations}/[tables] {关系} / [表]
Now we want to build the DAL for Person. 现在,我们要为人构建DAL。 How should the PersonBO look and when does the joins occure?
PersonBO的外观如何以及何时发生连接? Is it a business-layer problem to fetch all citynames and possible addressses pr.
获取所有城市名称和可能的地址是业务层问题吗? Person?
人? or should the DAL complete all this before returning the PersonBO to the BAL ?
还是DAL应该在将PersonBO返回BAL之前完成所有这些工作?
Class PersonBO
{
public int ID {get;set;}
public string Name {get;set;}
public List<AddressBO> {get;set;} // Question #1
}
// Q1: do we retrieve the objects before returning the PersonBO and should it be an Array instead? //问题1:我们是否在返回PersonBO之前检索对象,并且应该将其改为Array? or is this totally wrong for n-tier/3-tier??
还是对n层/ 3层完全错误?
Class AddressBO
{
public int ID {get;set;}
public string StreetName {get;set;}
public int PostalCode {get;set;} // Question #2
}
// Q2: do we make the lookup or just leave the PostalCode for later lookup? //问题2:我们进行查找还是将邮政编码留待以后查找?
Can anyone explain in what order to pull which objects? 谁能解释以什么顺序拉扯哪些物体? Constructive criticism is very welcome.
建设性的批评是非常受欢迎的。 :o)
:O)
You're kind of reinventing the wheel; 您是在重新发明轮子; ORMs already solve most of this problem for you and you're going to find it a little tricky to do yourself.
ORM已经为您解决了大多数此类问题,您将发现自己做起来有些棘手。
The way ORMs like Linq to SQL, Entity Framework and NHibernate do this is a technique called lazy loading of associations (which can optionally be overriden with an eager load). 诸如Linq to SQL,Entity Framework和NHibernate之类的ORM做到这一点的方法是一种称为关联的延迟加载的技术(可以选择通过快速加载来替代)。
When you pull up a Person
, it does not load the Address
until you specifically ask for it, at which point another round-trip to the database occurs (lazy load). 当您拉起
Person
,它不会加载Address
除非您明确要求,否则将再次进行数据库往返(延迟加载)。 You can also specify on a per-query basis that you want the Address
to be loaded for every person (eager load). 您还可以基于每个查询指定要为每个人加载
Address
(急切加载)。
In a sense, with this question you are basically asking whether or not you should perform lazy or eager loads of the AddressBO
for the PersonBO
, and the answer is: neither. 在某种意义上,从这个问题开始,您基本上是在问是否应该为
PersonBO
执行懒惰的或急切的AddressBO
加载,答案是:都不是。 There isn't one single approach that universally works. 没有一种方法可以普遍起作用。 By default you should probably lazy load, so that you don't do a whole lot of unnecessary joins;
默认情况下,您可能应该延迟加载,这样您就不会进行很多不必要的连接。 in order to pull this off, you'll have to build your
PersonBO
with a lazy-loading mechanism that maintains some reference to the DAL. 为了实现这一点,您必须使用延迟加载机制来构建
PersonBO
,该机制保留对DAL的一些引用。 But you'll still want to have the option to eager-load, which you'll need to build into your "business-access" logic. 但是,您仍然希望可以选择“预先加载”,这需要内置到“业务访问”逻辑中。
Another option, if you need to return a highly-customized data set with specific properties populated from many different tables, is to not return a PersonBO
at all, but instead use a Data Transfer Object (DTO). 如果需要返回具有从许多不同表填充的特定属性的高度定制的数据集,另一种选择是根本不返回
PersonBO
,而使用数据传输对象 (DTO)。 If you implement a default lazy-loading mechanism, you can sometimes substitute this as the eager-loading version. 如果您实现默认的延迟加载机制,则有时可以将其替换为快速加载版本。
FYI, lazy loaders in data access frameworks are usually built with the loading logic in the association itself: 仅供参考,数据访问框架中的惰性加载程序通常是使用关联本身中的加载逻辑构建的:
public class PersonBO
{
public int ID { get; set; }
public string Name { get; set; }
public IList<AddressBO> Addresses { get; set; }
}
This is just a POCO, the magic happens in the actual list implementation: 这只是一个POCO,魔术发生在实际的列表实现中:
// NOT A PRODUCTION-READY IMPLEMENTATION - DO NOT USE
internal class LazyLoadList<T> : IList<T>
{
private IQueryable<T> query;
private List<T> items;
public LazyLoadList(IQueryable<T> query)
{
if (query == null)
throw new ArgumentNullException("query");
this.query = query;
}
private void Materialize()
{
if (items == null)
items = query.ToList();
}
public void Add(T item)
{
Materialize();
items.Add(item);
}
// Etc.
}
(This obviously isn't production-grade, it's just to demonstrate the technique; you start with a query and don't materialize the actual list until you have to.) (这显然不是生产级的,只是为了演示该技术;您从查询开始,直到需要时才实现实际列表。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.