流畅的nhibernate没有在函数上正确生成模式

时间:2012-07-12 06:30:19

标签: nhibernate fluent-nhibernate

我有一种有趣的感觉,这只是我对nHibernate和Fluent nHibernate的理解。

我有一个小型控制台应用程序,它根据一堆实体类导出一个模式。一切都很好,直到我这样做:

    public virtual int UserId { get; set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
    public virtual string Email { get; set; }
    public virtual UserType UserType { get; set; }
    public virtual Client Client { get; set; }
    public virtual string UniqueIdentifier { get; set; }

    public virtual IList<UserAttribute> UserAttributes { get; set; }

    /** CODE IN QUESTION **/
    public virtual string GetAttributeValue(string name)
    {
        var value = UserAttributes.FirstOrDefault(ua => ua.AttributeDefinition.AttributeName == name);
        if (value != null)
            return value.Value;
        else
            return string.Empty;
    }

如果我注释掉这个功能,一切都很好。即使我只有函数返回string.Empty,一切正常。但是,一旦我添加了该行:

var value = UserAttributes.FirstOrDefault(ua => ua.AttributeDefinition.AttributeName == name);

所有内容都会出现此错误:

"The entity '<>c__DisplayClass1' doesn't have an Id mapped. Use the Id method to map your identity property. For example: Id(x => x.Id)."

我正在使用自动映射。这个错误的原因是什么?我通常理解错误,但看起来它在匿名类上失败了。我是否只是对这一切应该如何协同工作有一个错误的误解?我绝对是一个nHibernate新手,无论是在实践中还是在哲学上。我很乐意受到启发!

2 个答案:

答案 0 :(得分:6)

lambda ua => ua.AttributeDefinition.AttributeName == name生成一个内部类来捕获name参数。自动化程序遍历每个类型并尝试映射它,不幸的是还会选择生成的编译器。

您可以实现AutomappingConfiguration以排除编译器生成的类

class MyAutomappingConfiguration : DefaultAutomappingConfiguration
{
    public override bool ShouldMap(Type type)
    {
        return !type.IsDefined(typeof(CompilerGeneratedAttribute), false) && base.ShouldMap(type);
    }
}

答案 1 :(得分:0)

虽然@Firo上面的回答是有效的,但是当你在另一个Linq查询中有Linq查询时它似乎不起作用。例如:

DataTable Dt = FillData();
EnumerableRowCollection<DataRow> MasterProfileRows = null;
IList<RecordOwner> OwnedRecs = new List<RecordOwner>();
OwnedRecs.Add(new RecordOwner { ForeignRecordKey = 100 });
MasterProfileRows = from x in dt.AsEnumerable()
                    where OwnedRecs.Any(y => y.ForeignRecordKey.ToString() == x.Field<object>("ProfileID").ToString())
                    select x;

要解决这个问题,我将其添加到我的覆盖中以检查类的FullName中出现“__displayclass”的次数,如果它大于1,我们忽略映射它。

public override bool ShouldMap(Type type)
{
    // there is a bug where the fluent automapper tries to automap anonymous types within a lambda. the !type.IsDefined(typeof(CompilerGeneratedAttribute), false) works around this issue
    // except where there is a nest linq query.
    // see: 
    // https://github.com/jagregory/fluent-nhibernate/issues/146
    // http://stackoverflow.com/questions/11446155/fluent-nhibernate-not-generating-schema-correctly-on-function/11447966#11447966
    // http://stackoverflow.com/questions/14268568/odd-error-building-fluentnh-configuration
    // http://stackoverflow.com/questions/11446155/fluent-nhibernate-not-generating-schema-correctly-on-function/11447966
    // ignore nested linq queries (linq queries within linq queries) because they cause the auto mapper to error out.
    System.Text.RegularExpressions.Regex reg = new System.Text.RegularExpressions.Regex("__displayclass", System.Text.RegularExpressions.RegexOptions.IgnoreCase);
    if(reg.Matches(type.FullName).Count > 1)
        return false;

    return !type.IsDefined(typeof(CompilerGeneratedAttribute), false);
}