UnitOfWork具有延迟加载和多个数据源
本文关键字:数据源 延迟加载 UnitOfWork | 更新日期: 2023-09-27 17:57:54
我有跨两个数据存储区存储的业务对象。该对象的一部分存储在Azure表存储中,另一部分则存储在Azure SQL中。基本上,SQL部分用于查询,而表存储用于占用大量空间的属性。
大多数情况下,只使用对象的SQL部分(在SQL查询中)。只有当有人明确要求该对象时,才需要表存储属性。我试图实现的是一种设计,它将隐藏业务对象后面有两个数据源的事实,延迟加载存储表属性(因为执行SQL查询时不需要它们),并且仍然使代码可测试。
我目前的设计有一些POCO,它们是由一个工作单元创建的。我不想创建两个POCO,一个用于表存储,另一个用于SQL,所以我考虑了以下设计:
//Make the properties virtual
public class Customer
{
public virtual string Name {get;set;} //Stored in SQL
public virtual string Age {get;set;} //Stored in SQL
public virtual string Details {get;set;} // This prop is stored in Table Storage
}
//Create a derived internal POCO that can notify when a property is asked
internal class CustomerWithMultipleStorage
{
public event EventHandler OnDetailsGet;
public override string Details
{
get { if (OnDetailsGet!=null) OnDetailsGet( ... ); /* rest of the code */ }
set { /* code */ }
}
}
我的所有数据层代码都将使用CustomerWithMultipleStorage
,而DL之外的所有"外部"代码都使用Customer
,并且事件不会公开。现在,当工作单元返回Customer
时,它将只加载SQL属性并订阅Get事件。如果使用"客户"的用户需要其余属性,则会触发该事件,并加载"表存储"属性。
你觉得这个设计怎么样?这是正确的方法吗?你知道有更好的方法吗?
您可以使用带有依赖项注入的Lazy<T>
。请注意,这只是给你一些想法。
internal class CustomerWithMultipleStorage : Customer
{
private readonly ISqlDataLayer _sqlDataLayer;
private readonly ITableStorageDataLayer _tableStorageDataLayer;
private readonly Lazy<string> _details;
private string _detailsValue;
public CustomerWithMultipleStorage(ISqlDataLayer sqlDataLayer, ITableStorageDataLayer tableStorageDataLayer)
{
_sqlDataLayer = sqlDataLayer;
_tableStorageDataLayer = tableStorageDataLayer;
_details = new Lazy<string>(() => return (string)_tableStorageDataLayer.GetValue<Customer>(this, "Details"));
}
public override string Details
{
get
{
return (_detailsValue ?? (_detailsValue = _details.Value));
}
set
{
_detailsValue = value;
_tableStorageDataLayer.SetValue<Customer>(this, _detailsValue);
}
}
}
public interface ITableStorageDataLayer
{
object GetValue<T>(T item, [CallerMemberName] string property = "");
void SetValue<T>(T item, object value, [CallerMemberName] string property = "");
}
您也可以只使用一个数据层来映射每个对象的数据(稍后我将提供示例)。