首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在fluent NHibernate中将IUserType映射到组件属性

在fluent NHibernate中将IUserType映射到组件属性
EN

Stack Overflow用户
提问于 2011-06-16 12:01:27
回答 2查看 1.7K关注 0票数 2

我正在尝试为州和国家代码实现一个IUserType,它将允许我访问由两个字母组成的代码(存储在数据库中的代码)以及全名。我正在遵循NHibernate 3.0Cookbook(p.225)中的示例,但我的问题是我的StreetAddress类当前被映射为我的自动映射配置中的一个组件:

代码语言:javascript
复制
public override bool IsComponent(Type type)
{
    return type == typeof(StreetAddress);
}

由于该类被标识为组件,我不知道如何为component类的属性使用IUserType,因为该类没有显式映射。我无法告诉fluent NHibernate使用IUserType规范。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-06-21 03:58:00

@Firo很接近,但事实证明有一个更简单的解决方案。这里有两个步骤。首先,我必须告诉Fluent NHibernate不要映射StateCountry类,它们驻留在我的域层中:

代码语言:javascript
复制
public override bool ShouldMap(Type type)
{
    return type.Name != "State" && type.Name != "Country";
}

接下来,我只需为IUserType类创建约定。事实证明,这比@Firo建议的要容易:

代码语言:javascript
复制
public class CountryUserTypeConvention : UserTypeConvention<CountryType>
{
}

public class StateUserTypeConvention : UserTypeConvention<StateType>
{
}

这些IUserTypes的定义是从原始问题中引用的食谱中提取出来的,但如果您不想阅读它:

代码语言:javascript
复制
public class CountryType : GenericWellKnownInstanceType<Country, string>
{
    // The StateType is pretty much the same thing, only it uses "StateCode" instead of "CountryCode"
    private static readonly SqlType[] sqlTypes =
        new[] {SqlTypeFactory.GetString(2)};

    public CountryType()
        : base(new Countries(),
               (entity, id) => entity.CountryCode == id,
               entity => entity.CountryCode)
    {
    }

    public override SqlType[] SqlTypes
    {
        get { return sqlTypes; }
    }
}

这是从GenericWellKnownInstanceType派生的

代码语言:javascript
复制
[Serializable]
public abstract class GenericWellKnownInstanceType<T, TId> :
    IUserType where T : class
{
    private Func<T, TId, bool> findPredicate;
    private Func<T, TId> idGetter;
    private IEnumerable<T> repository;

    protected GenericWellKnownInstanceType(
        IEnumerable<T> repository,
        Func<T, TId, bool> findPredicate,
        Func<T, TId> idGetter)
    {
        this.repository = repository;
        this.findPredicate = findPredicate;
        this.idGetter = idGetter;
    }

    public Type ReturnedType
    {
        get { return typeof (T); }
    }

    public bool IsMutable
    {
        get { return false; }
    }

    public new bool Equals(object x, object y)
    {
        if (ReferenceEquals(x, y))
        {
            return true;
        }
        if (ReferenceEquals(null, x) ||
            ReferenceEquals(null, y))
        {
            return false;
        }
        return x.Equals(y);
    }

    public int GetHashCode(object x)
    {
        return (x == null) ? 0 : x.GetHashCode();
    }

    public object NullSafeGet(IDataReader rs,
                              string[] names, object owner)
    {
        int index0 = rs.GetOrdinal(names[0]);
        if (rs.IsDBNull(index0))
        {
            return null;
        }
        var value = (TId) rs.GetValue(index0);
        return repository.FirstOrDefault(x =>
                                         findPredicate(x, value));
    }

    public void NullSafeSet(IDbCommand cmd,
                            object value, int index)
    {
        if (value == null)
        {
            ((IDbDataParameter) cmd.Parameters[index])
                .Value = DBNull.Value;
        }
        else
        {
            ((IDbDataParameter) cmd.Parameters[index])
                .Value = idGetter((T) value);
        }
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Replace(object original,
                          object target, object owner)
    {
        return original;
    }

    public object Assemble(object cached, object owner)
    {
        return cached;
    }

    public object Disassemble(object value)
    {
        return value;
    }

    /// <summary>
    /// The SQL types for the columns
    /// mapped by this type.
    /// </summary>
    public abstract SqlType[] SqlTypes { get; }
}

这些类的存储库只是一对StateCountry对象的ReadOnlyCollection。再一次,从食谱中:

代码语言:javascript
复制
public class States : ReadOnlyCollection<State>
{
    // Truncated in the interest of brevity
    public static State Arizona = new State("AZ", "Arizona");
    public static State Florida = new State("FL", "Florida");
    public static State California = new State("CA", "California");
    public static State Colorado = new State("CO", "Colorado");
    public static State Oklahoma = new State("OK", "Oklahoma");
    public static State NewMexico = new State("NM", "New Mexico");
    public static State Nevada = new State("NV", "Nevada");
    public static State Texas = new State("TX", "Texas");
    public static State Utah = new State("UT", "Utah");

    public States() : base(new State[]
                               {
                                   Arizona, Florida, California, Colorado,
                                   Oklahoma, NewMexico, Nevada, Texas, Utah
                               }
        )
    {
    }
}

希望这能帮助到外面的人。

票数 6
EN

Stack Overflow用户

发布于 2011-06-17 14:53:35

我无法对其进行测试,但应该可以使用约定

代码语言:javascript
复制
public class ComponentConvention : IComponentConvention, IComponentConventionAcceptance
{
    public void Accept(IAcceptanceCriteria<IComponentInspector> criteria)
    {
        criteria.Expect(x => x.Type == typeof(StreetAddress);
    }

    public void Apply(IComponentInstance instance)
    {
        instance.Properties.First(p => p.Name == "CountrCode").CustomType<MyUserType>();
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6366956

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档