2012-03-21 2 views
1

私は WCFサービスに対して複雑なクエリを作成する必要があるプロジェクトに取り組んでいます。linq to sqlバックエンドを使用したWCFによるDTOオブジェクトのクエリ

サービスは、バックエンドでLINQ to SQLのを使用して、データ転送に照会を投影し、このようなオブジェクト:私は何をしたいか

 

    dbContext.GetQueryable() 
        .Where(x => x.Id == formatId) 
        .Select(x => FormatHelper.PopulateMSFormat(x)) 
        .ToList(); 

クライアント側のクエリを指定することで、私がしたいと言うことができます特定のプロパティを持つすべてのフォーマットまたはそれらの2つのフォーマットを照会します。このスタイルで 何か:

 

    var assets = client.QueryForAssets().Where(x => (x.name == "Test" || x == "Arne") && x.doe == "john"); 

IAMの私はWCF上のIQueryableを返すが、そのようなことは、ODataのサービスで行うことができることができないことに注意してください。問題は、DTOとODataを返さなければならないということです。私は、データモデルを公開するL2S-datacontextに簡単にバインドさせて、DTOは公開しません。

効率的にL2レイヤに伝播するDTOに対してクエリをシリアル化する良い方法はありますか?

私は独自のクエリ言語を書くことを考えましたが、DTOからlinqクラスへのマッピングがないため、正しい式ツリーをl2sの述語として構築するのはかなり難しいことがわかりました。

答えて

2

ODataサービスでは、データベースエンティティを直接返すことはありません。クエリ可能な形式でDTOを返すだけです。そして、LINQのSelect()方法の助けを借りて、あなたは単純にクエリを提供する前にDTOに任意のデータベース・エンティティを変換することができます

public class DataModel 
{ 
    public DataModel() 
    { 
    using (var dbContext = new DatabaseContext()) 
    { 
     Employees = from e in dbContext.Employee 
        select new EmployeeDto 
        { 
        ID = e.EmployeeID, 
        DepartmentID = e.DepartmentID, 
        AddressID = e.AddressID, 
        FirstName = e.FirstName, 
        LastName = e.LastName, 
        StreetNumber = e.Address.StreetNumber, 
        StreetName = e.Address.StreetName 
        }; 
    } 
    } 

    /// <summary>Returns the list of employees.</summary> 
    public IQueryable<EmployeeDto> Employees { get; private set; } 
} 

あなたは簡単にこのようなのODataサービスとしてこれを設定することができます。

public class EmployeeDataService : DataService<DataModel> 

実装の詳細については、see thisをご覧ください。 ODataサービスは、一度手に入れると非常に強力です。

+0

良い解決策のように思えますが、うまく動作しません。私はそれが、EFではなくL2Sを使用しているという事実と関係があると考えています –

+0

少なくとも2つの問題が見つかりました。私はヘルパーメソッドを使用することはできませんし、コンテキストがラップされているので、コレクションが照会されたときにそれが破棄されます。 –

+0

L2SまたはEFの使用は問題ありません。任意のソースからデータをプールできます。 ODataサービスオブジェクトは「要求ごとに」作成されるため、 'DataModel'クラスのインスタンスが要求と共に作成され、破棄されるため、' using'ステートメントが正しい方法です。 –

0

ODataサービスを使用してDTOを返すことができると私は信じています。

http://www.codeproject.com/Articles/135490/Advanced-using-OData-in-NET-WCF-Data-Servicesをご覧ください。特に、「データベースの変換を公開する」セクション。エンティティオブジェクトをDTOにフラット化し、このDTOモデルに対してクライアントがクエリを実行できるようにすることができます。

これはあなたが探しているものですか?

0

複雑なエンティティが長い場合は、手動で投影を作成するのは悪夢です。 AutomapperはLINQがIQueryableと組み合わせて使用​​できないため動作しません。

ここでこれは完璧なソリューションです:Stop using AutoMapper in your Data Access Code

それはあなたのための「魔法」の投影を生成し、あなたのDTO(データ転送オブジェクト)クラスに基づいてのODataクエリを実行することができます。

[Queryable] 
    public IQueryable<DatabaseProductDTO> GetDatabaseProductDTO(ODataQueryOptions<DatabaseProductDTO> options) 
    { 
     // _db.DatabaseProducts is an EF table 
     // DatabaseProductDTO is my DTO object 
     var projectedDTOs = _db.DatabaseProducts.Project().To<DatabaseProductDTO>(); 

     var settings = new ODataQuerySettings(); 
     var results = (IQueryable<DatabaseProductDTO>) options.ApplyTo(projectedDTOs, settings); 

     return results.ToArray().AsQueryable(); 
    } 

私は

/odata/DatabaseProductDTO?$filter=FreeShipping eq true 

ノートでこれを実行します。この記事では、数年前からのものであり、それは今AutoMapperでに建てられ、このような機能を持っている可能性があります私は時間を持っていない私は。今すぐこれをチェックしてください。上の参照記事のインスピレーションは、AutoMapper自体の著者によるthis articleに基づいていました。そのため、いくつかの改良されたバージョンが含まれている可能性があります。一般的なコンセプトは素晴らしく、このバージョンは私のためにうまくいきます。

関連する問題