UnitOfWork具有延迟加载和多个数据源

时间:2013-02-06 17:24:09

标签: c# asp.net-mvc azure-sql-database azure-storage

我的业务对象存储在两个数据存储中。对象的一部分存储在Azure表存储中,另一部分存储在Azure SQL中。基本上,SQL部分用于查询,而表存储用于占用大量空间的属性。

大多数情况下,只使用对象的SQL部分(在SQL查询中)。仅当有人明确要求该对象时才需要表存储属性。我想要实现的是一种设计,它将隐藏业务对象背后有两个数据源的事实,延迟加载存储表属性(因为在执行SQL查询时不需要它们)并且仍然使代码可测试。 / p>

我目前的设计中有一些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事件。如果使用客户的人需要其余属性,则将触发该事件并加载表存储属性。

您对此设计有何看法?这是正确的方法吗?你知道更好的方法吗?

1 个答案:

答案 0 :(得分:1)

可以使用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 = "");
}

您也可以使用包含每个对象的映射数据的数据层(我稍后会提供示例)。