【问题标题】:Fluent NHibernate automapping流畅的 NHibernate 自动映射
【发布时间】:2011-09-08 21:43:44
【问题描述】:

我只是想知道是否可以使用 Fluent NHibernate 自动映射 .Net TcpClient 对象?

我有一个类,它有一个我想映射的 TcpClient 属性。

我尝试创建一个从 TcpClient 继承的名为 tTcpClient 的自定义类,并添加一个带有 getter/setter 的 Id 属性;但是,它仍在寻找基类的 Id 字段。

如果可能的话,任何人都有任何想法,或者我需要为 TcpClient 创建自己的 xml 映射吗?

我有点希望能够保存该对象,以便在重新加载应用程序时轻松地重新创建它,并将 TcpClient 对象的属性绑定到 PropertiesGrid 并允许通过这相当容易的方式进行配置。

谢谢。

【问题讨论】:

    标签: nhibernate fluent-nhibernate nhibernate-mapping fluent-nhibernate-mapping


    【解决方案1】:

    NHibernate 不知道如何处理开箱即用的 TcpClient 等复杂类型。但它允许您提供自己的加载和存储代码。你可以使用IUserType:

    public class TcpClientMapper : IUserType {
    
        public SqlType[] SqlTypes {
            get {
                return new[] { 
                               new SqlType(DbType.String), 
                               new SqlType(DbType.Int32) 
                             };
            }
        }
    
        public Object NullSafeGet(IDataReader rs, String[] names, ...) {
    
            String address = NHibernateUtil.String.NullSafeGet(rs, names[0]);
            Int32 port = NHibernateUtil.Int32.NullSafeGet(rs, names[1]);
    
            return new TcpClient(address, port);
        }
    
        public void NullSafeSet(IDbCommand cmd, Object value, Int32 index) {
            TcpClient tcpClient = value as TcpClient;
            if(tcpClient == null) {
                NHibernateUtil.String.NullSafeSet(cmd, null, index);
                NHibernateUtil.Int32.NullSafeSet(cmd, null, index + 1);
            } else {
                EndPoint red = tcpClient.Client.RemoteEndPoint;
                IPEndPoint endpoint = ((IPEndPoint)red);
                NHibernateUtil.String.Set(cmd, endpoint.Address.ToString(), index);
                NHibernateUtil.Int32.Set(cmd, endpoint.Port, index + 1);
            }
        }
    
        public Type ReturnedType {
            get { return typeof(TcpClient); }
        }
    
        // TODO: implement other methods
    }
    

    并在 hbm 中像这样映射它:

    <property name="_tcpClient" type="MyNamespace.TcpClientMapper, MyAssembly">
        <column name="Address" />  <!-- NullSafeGet/Set index == 0 -->
        <column name="Port" />     <!-- NullSafeGet/Set index == 1 -->
    </property>
    

    或者使用流利的UserTypeConvention:

    public class TcpClientUserTypeConvention : UserTypeConvention<TcpClientMapper> {
    }
    

    【讨论】:

    • 我明白了。我必须为 IUserType 实现所有方法,然后我假设它才能工作?如果是这样,您将如何为此实施 NullSafeSet?我的类本身的属性仍然是常规的 TcpClient 权限,还是我需要将其更改为 ClientMapper 类?
    • 是的,你必须实现所有的方法,不难,看看答案中的链接。属性仍然是一个常规的 TcpClient(从设计的角度来看这有点奇怪)。请参阅 NullSafeSet 实施的最后编辑。
    • 看起来不错,感谢您的帮助。另一个快速的问题?你怎么知道发送到 Strings[] 数组的顺序?我意识到您正在阅读属性,但您怎么知道地址在数组中的位置 0 和端口在位置 1?我问的原因是 b/c 我正在尝试为串行连接实现相同的功能。
    • 查看我上次的编辑,列在映射文件中列出,在 IUserType 实现中使用相同的顺序。
    • 另外一件事。在实现之后,当我尝试使用包含 TcpClient 的 ConnectionTCP 保存对象时,我得到一个 {"Failed to convert parameter value from a IPAddress to a Byte[]."} 异常。我查看了 NullSafeSet ,它似乎在提取正确的值。有什么想法吗?
    【解决方案2】:

    内森,

    你看过这个项目吗?

    http://automapper.org/

    干杯

    【讨论】:

    • 这应该像 Fluent 的自动映射功能还是类似的功能?
    • 我几乎认为这是完全题外话,但后来意识到您可以实际上使用自动映射器作为解决此问题的一部分。我会尽快写详细信息。
    • 首先创建一个单独的类,该类包含您希望 NHibernate 持久保存到数据库的所有数据。然后使用 AutoMapper(一种将数据从一个对象复制到另一个对象的工具)将值从持久对象移动到 TcpClient 实例上。
    • 所以如果我有一个 ConnectionTCP 类,它有一个 TcpClient 属性,我只是使用 AutoMapper 来映射 ConnectionTCP 类?您如何从中获得 NHibernate 映射?
    猜你喜欢
    • 2011-03-13
    • 1970-01-01
    • 2023-03-14
    • 2010-11-22
    • 2013-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-19
    相关资源
    最近更新 更多