1

私のデータベースには、システム全体で使用される値のシステム コード ルックアップを含む 1 つの大きな「コード」テーブルがあります。そのようです:

[TableName("code_entries")]                         public class Code {
    [MapField("code_nbr")][PrimaryKey, Identity]    public int Id;
    [MapField("code")]                              public string Value;
}

私は BLToolkit を初めて使用します。これまでに見た静的なマッピングに似た概念があることを期待していますが、これにより、他のテーブルで発生したこれらのコードをそれぞれの値に簡単にマップできるようになります。例えば:

    [TableName("person")]                               public class Person {
        [MapField("person_nbr")][PrimaryKey, Identity]  public int Id;
        [MapField("dob")][Nullable]                     public int BirthDate;
        [MapField("eye_color")][Nullable]               public int EyeColorCode;
        [MapField("hair_color")][Nullable]              public int HairColorCode;    
}

上記の EyeColorCode と HairColorCode が Codes テーブルの値にマップされている場合、OR クラス内でそのデータをマップし、単一のクエリでオブジェクト全体を取得する簡単な方法を作成できますか?

私は次のようなもので終わりたいです:

// person.Id = 1
// person.DOB = some date
// person.EyeColor = "Blue"
// person.HairColor = "Brown"
4

2 に答える 2

2

ありがとうデビッド。私はあなたのアプローチに行きましたが、私からの痛みを少し軽減するために少し修正しました。あなたの例のように、クラスに関連付けを追加しました。

[Association(ThisKey = "EyeColorCode", OtherKey = "Id")]    public Code EyeColor { get; set; }
[Association(ThisKey = "HairColorCode", OtherKey = "Id")]   public Code HairColor { get; set; }

次に、拡張メソッドを書きました。新しいオブジェクトを受け取り、すべての書き込み可能なプロパティをソース オブジェクトにマージします。これを使用すると、クエリですべてのプロパティを指定する必要がなくなります。つまり、次のようになります。

from p in db.Person
select p.PropertyUnion(new Person() {
{
    EyeColor  = p.EyeColor,
    HairColor = p.HairColor
};

これにより、いくつかのより複雑なオブジェクトのコードをかなり節約でき、より読みやすくなると思います。拡張メソッドのコードは次のとおりです。

/// <summary>
/// Union by retrieving all non-null properties from source parameter and setting those properties on the instance object
/// </summary>
public static T PropertyUnion<T>(this T destination, T source) {
    // Don't copy from a null object
    if (Object.ReferenceEquals(source, null) || Object.ReferenceEquals(destination, null)) {
        return destination;
    }
    // copy properties
    foreach (var property in source.GetType().GetProperties()) {
        if (!property.CanWrite || !property.CanRead)
            continue;
        var match = destination.GetType().GetProperty(property.Name);
        if (!match.CanWrite || !match.CanRead)
            throw new MethodAccessException("Matching property '" + match.Name + "' must allow both read and write operations.");
        var value = property.GetValue(source, null);
        if (value != null && !value.Equals(Activator.CreateInstance(property.PropertyType)))
            match.SetValue(destination, value, null);
    }
    return destination;
}

ご協力いただきありがとうございます。

于 2012-03-12T16:58:57.553 に答える
1

それは本当にあなたが望んでいたものではありませんが、あなたは協会を使うことができます

これをPersonクラスに追加できます

[Association(ThisKey="eye_color", OtherKey="code_nbr", CanBeNull=true)]
public Code EyeColor;

[Association(ThisKey="hair_color", OtherKey="code_nbr", CanBeNull=true)]
public Code HairColor;

そして、次のようなことをします

from p in db.Person
select new
{
    Id        = p.Id,
    DOB       = p.BirthDate,
    EyeColor  = p.EyeColor.Value,
    HairColor = p.HairColor.Value
};

とにかく、これらはほとんど変更されないタイプのコードのようです。私は通常、起動時にこれらをクライアントに配置し、データを表示するときに説明を入力すると、すべてがはるかに簡単になります。IDが見つからない場合は、コレクションを更新するだけです

于 2011-12-22T17:02:19.090 に答える