2

これは、nHibernateとFluentnHibernateについての私の理解にすぎないという面白い感じがします。

一連のエンティティクラスに基づいてスキーマをエクスポートする小さなコンソールアプリケーションがあります。私がこれを行うまで、すべてがうまく機能します:

    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;
    }

関数をコメントアウトすると、すべてがうまく機能します。関数returnstring.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の初心者です。啓発されたい!

4

2 に答える 2

6

ラムダ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);
    }
}
于 2012-07-12T08:37:01.043 に答える
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);
}
于 2013-10-22T16:59:24.953 に答える