1

1 つはサードパーティの API から、もう 1 つはデータベースからの異なるオブジェクトの 2 つのリストがあり、2 つを関係としてリンクしようとしています。理想的には、DBML が外部キーを持つテーブルの関係を作成する方法と同様の効果があります ( Customer.Orders)。

サードパーティから:

class ApiObject {
    public string ID { get; set; }
    public string Title { get; set; }
    public DateTime CreatedDate { get; set; }
    ... 30 other properties ...
}

私のデータベースから:

class DbmlObject {
    public int ID { get; set; }
    public string ApiID { get; set; }
    public string OtherString { get; set; }
}

それらは関連していますApiObject.ID == DbmlObject.ApiID

これらをマージしたり、匿名オブジェクトに結合したり(および30以上のプロパティを明示的にリストしたり)したくはありませんがDbmlObject、リンクされたプロパティをApiObject. つまり、次のようにアドレス指定 できます。apiObject.DbmlObjects.First().OtherString理想的apiObject.DbmlObject.OtherStringには、1 対 1 の関係であるためです。

コントローラーで:

List<ApiObject> apiObjects = _thirdParty.GetObjects();

DbmlDataContext model = new DbmlDataContext();
List<DbmlObject> dbmlObjects = model.GetAllDbmlObjects();

// relate them here

foreach (var apiObject in apiObjects)
    Console.Write(apiObject.DbmlObject.OtherString)
// NOTE: ideally this foreach loop should not make a DBML query on each iteration, just the single GetAllDbmlObjects query above.
4

1 に答える 1

2

次のように聞こえますjoin

var combined = from api in apiObjects
               join dbml in dbmlObjects on api.ID equals dbml.ApiID
               select new { api, dbml }

ApiObject 内の DbmlObject を取得するには、ApiObject を継承してそのクラスの新しいクラス (Dbml プロパティを含む) を作成する、まったく新しいクラスを作成して返す必要があります。静的型付けが必要な場合は、これが最善の方法です。もちろん、必要なものを取得するために (誤って) 使用dynamicすることもできます。

この場合、(コメントで) ApiObject クラスは変更できないサード パーティのライブラリからのものであると言及しています。この場合、おそらく、コンストラクターで両方のオブジェクトのインスタンスを取る新しい型を作成することを選択します。必要なプロパティ (デコレータ) を公開します。はい、多くのコードのように見えますが、複雑ではありません。優れたツールが自動生成し、コードを簡潔にするために必要なクラスを取得します。

をさらに返したい場合は、それにIEnumerable<dynamic>基づいて「結合動的」オブジェクトを作成しDynamicObject、ApiObject と DbmlObject のすべてのプロパティに応答するか、単に DbmlObject をプロパティとして追加します。これが正しい方法であると言っているのではありません。それはあなたが何のためにそれを必要としているかによって異なります - タイプセーフを失っていることを覚えておいてください。簡単な例を次に示します。

void Main()
{
    dynamic dyn = new CombiningDynamic(new Foo { X = 3 }, new Bar { Y = 42 });
    Console.WriteLine(dyn.X);
    Console.WriteLine(dyn.Y);
}

public class Foo
{
    public int X {get;set;}
}

public class Bar 
{
    public int Y { get;set;}
}

public class CombiningDynamic : DynamicObject
{
    private object [] innerObjects;


    public CombiningDynamic(params object [] innerObjects) 
    {
        this.innerObjects = innerObjects;

    }
    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        foreach(var instance in innerObjects) 
        {
            Type t = instance.GetType();
            PropertyInfo prop = t.GetProperty(binder.Name);
            if (prop != null && prop.CanRead) 
            {
                result = prop.GetValue(instance, null);
                return true;
            }
        }
        result = null;
        return false;
    }
}

これはサンプルコードです。本当にこの方法を使用する場合は、おそらくさらにいくつかのメソッド (TrySetMember など) をオーバーライドする必要があり、リフレクションの結果をキャッシュして、毎回型を確認する必要がないようにする必要があります。反射は(比較的)遅いです。

于 2012-07-17T20:28:00.793 に答える