使用NHibernate,我如何创建INHibernateProxy?

时间:2010-06-16 15:07:57

标签: nhibernate automapper dto

经过大量关于序列化的阅读后,我决定尝试创建DTO。经过更多阅读,我决定使用AutoMapper。

我想要做的是转换父(很容易)并转换实体属性(如果它们已经初始化),我已经使用ValueResolvers完成,如下所示(我可能会尝试使它成为通用的一旦我得到它完全工作)。这部分有效。

public class OrderItemResolver : ValueResolver<Order, OrderItem>
{
    protected override OrderItem ResolveCore(Order source)
    {
        // could also use NHibernateUtil.IsInitialized(source.OrderItem)
        if (source.OrderItem is NHibernate.Proxy.INHibernateProxy)
            return null;
        else
            return source.OrderItem;
        }
    }
}

当我将DTO转换回实体时,对于未初始化的实体,我想创建一个代理,这样如果实体想要访问它,它就可以。但是,我无法弄清楚如何创建代理。如果那是相关的,我正在使用Castle。

我尝试过一堆没有运气的东西。下面的代码是一团糟,主要是因为我一直在尝试随意而不知道我应该做什么。有人有什么建议吗?

public class OrderItemDTOResolver : ValueResolver<OrderDTO, OrderItem>
{
    protected override OrderItem ResolveCore(OrderDTO source)
    {
        if (source.OrderItem == null)
        {
            //OrderItem OrderItem = new ProxyGenerator().CreateClassProxy<OrderItem>(); // Castle.Core.Interceptor.

            //OrderItem OrderItem = new ProxyGenerator().CreateClassProxy<OrderItem>();
            //OrderItem.Id = source.OrderItemId;

            //OrderItem OrderItem = new OrderItem();
            //var proxy = new OrderItem() as INHibernateProxy;
            //var proxy = OrderItem as INHibernateProxy;
            //return (OrderItem)proxy.HibernateLazyInitializer
            //ILazyInitializer proxy = new LazyInitializer("OrderItem", OrderItem, source.OrderItemId, null, null, null, null);
            //return (OrderItem)proxy;
            //return (OrderItem)proxy.HibernateLazyInitializer.GetImplementation();

            //return OrderItem;

            IProxyTargetAccessor proxy = new Castle.Core.Interceptor.

            var initializer = new LazyInitializer("OrderItem", typeof(OrderItem), source.OrderItemId, null, null, null, null);
            //var proxyFactory = new SerializableProxyFactory{Interfaces = Interfaces, TargetSource = initializer, ProxyTargetType = IsClassProxy};

            //proxyFactory.AddAdvice(initializer);
            //object proxyInstance = proxyFactory.GetProxy();
            //return (INHibernateProxy) proxyInstance;
            return null;


            //OrderItem.Id = source.OrderItemId;
            //return OrderItem;
        }

        else
            return OrderItemDTO.Unmap(source.OrderItem);
    }
}

谢谢, 埃里克

也许我过于复杂了。这似乎有效。有人看到任何问题吗?

public class OrderItemDTOResolver : ValueResolver<OrderDTO, OrderItem>
{
    protected override OrderItem ResolveCore(OrderDTO source)
    {
        if (source.OrderItem == null)
            return NHibernateSessionManager.Instance.Session.GetISession().Load<OrderItem>(source.AgencyId);

        else
            return OrderItemDTO.Unmap(source.OrderItem);
    }
}

1 个答案:

答案 0 :(得分:1)

这可能是答案是“不”,或者至少“你可能不应该”的情况之一。如果您直接将DTO映射到NHibernate映射对象,那么您实际上并不是将映射对象用作域对象,而是将数据推入和导出数据库的奇特方式。这当然可能是你所追求的,但过去我自己做过这一点,我发现试图在两个方向上使用相同的DTO数据格式是有问题的。如果您要进行跨进程,则会将服务转换为(难以维护的)CRUD层。如果你在同一个过程中,你正在使用DTO进行不必要的数据改造。

发送DTO很好,但考虑将数据投影到与客户实际需要的更紧密对齐的格式。在特定的DTO中更好地表达您所获得的内容,这些DTO仅表示执行实际操作所需的数据(本质上是Command对象)。有了一些自动属性,它们很容易构建。然后,您可以拥有一个业务方法,该方法仅使用必要的信息执行必要的操作,并且采用适合于正在执行的操作的格式。我最近主要使用AutoMapper(它确实摇滚)是将传入的DTO转换为域方法可以使用的类型。

此外,映射对象上的公共setter是不合需要的,因为它们允许任何代码操纵对象而无需任何验证。这意味着对它们的任何修改都可能使它们处于无效状态。

如果你真的不关心上面的内容(它并不总是适用)你加载单个实例的方式会让你打开做多个单独的数据库加载,这是一个潜在的性能问题。