PetaPoco透明延迟装载

时间:2014-04-30 06:39:25

标签: c# petapoco castle-dynamicproxy

我在以前的企业应用程序中使用过NHibernate,但其复杂的设置和分散的文档正在促使我尝试在我的下一个应用程序中使用更简单的PetaPoco。我面临的主要问题是实现透明延迟加载以支持以下场景:

public class Customer {
    public string CustomerName { get; set; }
    public List<Order> Orders { get; set; } // Orders should be lazy-loaded
}

public class Order {
    public Int32 OrderNumber { get; set; }
    public List<Product> Products { get; set; } // Products should be lazy-loaded
}

public class Product {
    public string ProductName { get; set; }
}

我认为我需要使用Castle DynamicProxy,但我正在努力了解如何实现拦截器来拦截对getter的调用并触发相关订单或产品的检索。此外,一旦我有拦截器,当我使用PetaPoco检索数据时如何确保它被使用?

非常感谢任何协助。

提前致谢。


编辑:@Groo:我想在PetaPoco选择函数上面创建一个图层来为相关集合添加拦截器(使用自定义属性),例如:

public class ReferencedByAttribute : Attribute
{
    public String ForeignKeyPropertyName { get; set; }
    public ReferencedByAttribute(String foreignKeyPropertyName)
    {
        this.ForeignKeyPropertyName = foreignKeyPropertyName;
    }
}

using Castle.DynamicProxy;
public class LazyLoadingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // TODO: Intercept first call to getter and retrieve related objects from the database
        invocation.Proceed();
    }
}

public class PetaPocoWrapper {
    public List<T> Fetch<T>(String sql) {
        PetaPoco.Database db = new PetaPoco.Database("connectionstring");
        List<T> entities = db.Fetch<T>(sql);
        ProxyGenerator generator = new ProxyGenerator();
        foreach(T entity in entities)
        {
            foreach (PropertyInfo pi in entity.GetType().GetProperties())
            {
                if (pi.GetCustomAttributes(typeof(ReferencedByAttribute), true).Count() == 1) {
                    pi.SetValue(entity, generator.CreateClassProxy(pi.PropertyType, new LazyLoadingInterceptor()), null);
                }
            }
        }
        return entities;
    }
}

1 个答案:

答案 0 :(得分:0)

你必须采用老式的方式

    private IList<Product> _Items;
    public IList<Product> Items {
        get {
            if (_Items == null) {
                _Items = DbHelper.CurrentDb().Fetch<Product>("SELECT ..");
            }
            return _Items;
        }
        set {
            _Items = value;
        }
    }