如何让NHibernate映射到自定义类?

时间:2017-10-26 14:49:37

标签: c# nhibernate

我最近问过一个非常类似的问题,但是虽然标题提到了课程,但我的内容主要是指一个元组,而(非常好的)答案反映了这一点。当我试图用一个类代替元组时,我得到TargetParameterCountException: Parameter count mismatch.异常。

How can I get NHibernate to map to a Tuple or Class?

我有以下方法从数据库中获取结果列表。

public static IList<T> Find<T>(DetachedCriteria crit) where T : class
{
    lock (_locker)
    {
        return crit.GetExecutableCriteria(InstanceSession)
            .List<T>();
    }
}

这通常很有效。但是,我已经更改了一个调用上述方法的方法。

public IList<FooBarResult> FindResults(FooBarTask st)
{
    return DataAccess.Find<FooBarResult>(DetachedCriteria.For<FooBarResult>()
        .Add(Restrictions.Eq("Task", st))).ToList();
}

哪个适用于此(因为我不想返回整个FooBarResult,只有某些列)。

public IList<MyCustomClass> FindResults(FooBarTask st)
{
    var typeConstructor = typeof(MyCustomClass).GetConstructors()[0];
    return DataAccess.Find<MyCustomClass>(DetachedCriteria.For<FooBarResult>()
        .Add(Restrictions.Eq("Task", st))
        .SetProjection(
            Projections.ProjectionList()
                .Add(
                    Projections.Property("FieldOne") //this is a DateTime
                )
                .Add(
                    Projections.Property("FieldTwo") //this is a Guid
                )
                .SetResultTransformer(Transformers.AliasToBeanConstructor(typeConstructor))
        )
    );
}

这就是上课。

public class MyCustomClass
{
    public MyCustomClass()
    {
        //placeholder
    }

    public MyCustomClass(DateTime FieldOne, Guid FieldTwo)
    {
        this.FieldOne = FieldOne;
        this.FieldTwo = FieldTwo;
    }

    public DateTime FieldOne { get; set; }
    public Guid FieldTwo { get; set; }
}

如前所述,在运行return crit.GetExecutableCriteria(InstanceSession).List<T>();代码时,我得到TargetParameterCountException: Parameter count mismatch.例外。

有什么方法可以让它返回我MyCustomClass的列表吗?

2 个答案:

答案 0 :(得分:2)

我没有对此进行过测试,但您应该使用Transformers.AliasToBean查看别名以使变换器工作:

public IList<MyCustomClass> FindResults(FooBarTask st)
{
    var typeConstructor = typeof(MyCustomClass).GetConstructors()[0];
    return DataAccess.Find<MyCustomClass>(DetachedCriteria.For<FooBarResult>()
        .Add(Restrictions.Eq("Task", st))
        .SetProjection(
            Projections.ProjectionList()
                .Add(Projections.Property("FieldOne"), "FieldOne")
                .Add(Projections.Property("FieldTwo"), "FieldTwo")        
        )
        .SetResultTransformer(Transformers.AliasToBean(typeof(MyCustomClass)))
        .List<MyCustomClass>()
}

答案 1 :(得分:1)

在这一行:

var typeConstructor = typeof(MyCustomClass).GetConstructors()[0];

你将得到第一个默认构造函数,它的签名显然不匹配。对您的案例最简单的解决方法是:

var typeConstructor = typeof(MyCustomClass).GetConstructors()[1];

但最干净的解决方案将是这些方面(未经测试,也有点简化):

var typeConstructor = GetMatchingConstructorOrThrow<MyCustomClass>
    (typeof(DateTime), typeof(Guid));

// ...

private ConstructorInfo GetMatchingConstructorOrThrow<T>(params Type[] requiredSignature)
where T : class
{
    foreach (var c in typeof(T).GetConstructors())
    {
        var currentSignature = c.GetParameters().Select(p => p.ParameterType);
        if (currentSignature.SequenceEqual(requiredSignature))
        {
            return c;
        }
    }

    throw new NoMatchingConstructorFoundException();
}