2017-05-24 14 views
2

私はおそらく非常に単純な問題を抱えています。私のデータベースで は、私には、次の表があります。NHibernateは、関連する子オブジェクトを持つオブジェクトのリストをQueryOverで選択します。

tblOrder 
----------------- 
Id 
OrderStatusId 

tblOrderStatus 
----------------- 
Id 
Name 

をそして私は私のプロジェクトで、次のマッピングを行った。

[Class(NameType = typeof(Order), Table = "tblOrder") 
public class Order { 
    [Id(-2, Name = "Id")] 
    [Generator(-1, Class = "native")] 
    public virtual long Id { get; set; } 

    [ManyToOne] 
    public virtual OrderStatus Status { get; set; } 
} 

[Class(NameType = typeof(OrderStatus), Table = "tblOrderStatus")] 
public class OrderStatus { 
    [Id(-2, Name = "Id")] 
    [Generator(-1, Class = "native")] 
    public virtual long Id { get; set; } 

    [Property] 
    public virtual string Name { get; set; } 
} 

クエリがIList<OrderSummary>を返す必要があります。クラスOrderSummaryにはプロパティStatusがあります。ここでStatusIdNameプロパティを持つオブジェクトです。これは、KeyValuePairまたはタイプOrderStatusのいずれか(どちらが最善で動作するか)のいずれかである可能性があります。注文を取得することは問題ではありませんが、OrderStatusをオブジェクトとして追加することは、私が問題を抱えている部分です。 また、クエリの結果をJSONとしてクライアントに返す必要があります。

OrderSummaryは次のようになります。私の最初のバージョンOrderSummary

public class OrderSummary { 
    public long Id { get; set; } 
    public OrderStatus Status { get; set; } 
} 

OrderStatusIdOrderStatusNameのための独立した性質を有していました。これは動作しますが、私はこれらの別々のプロパティを避けようとしています。 私はSelectSubQueryでこれを試しましたが、サブクエリに複数のフィールドを返すため、エラーが返されます。

-----------------------------------アップデート----------

var query = session.QueryOver<OrderStatus> 
    .Fetch(o => o.Status).Eager 
    .JoinAlias(o => o.Status,() => statusAlias, JoinType.LeftOuterJoin); 

問題は次のとおりです。-------------------

フレディTrebouxのアドバイスに続いて、私は次のクエリの結果Eagerを使用して、私のクエリを変更しました、私は、データを選択していないが、検索されたStatusを変換し、それをOrderSummary.Statusに割り当てる方法を見つけましたか?私は以下を試した:

OrderSummary orderAlias = null; 
query.SelectList(list => list 
    .Select(o => o.Id).WithAlias(() => orderAlias.Id) 
    .Select(() => statusAlias).WithAlias(() => orderAlias.Status) 
).TransformUsing(Transformer.AliasToBean<OrderSummary>()); 

-------------------------------- ANSWER ---- ------------------------------

最後に編集したように、この問題は実際の選択はOrderStatusですが、それをクライアントに返します。だから、NHibernateの知識が不足していると思ったのですが、[JsonObject]属性をOrderStatusクラスに追加するだけで簡単でした。私の愚かなこと。

は、私は次のように私のクエリを変更している:私は現在、それが不可能だと怖い

Order orderAlias = null; 
OrderSummary orderSummary = null; 
OrderStatus statusAlias = null; 
var query = session.QueryOver<Order>(() => orderAlias) 
    .JoinAlias(() => orderAlias.Status,() => statusAlias, JoinType.LeftOuterJoin); 

query = query 
    .Select(
     Projections.ProjectionList() 
      .Add(Projections.Property(() => orderAlias.Id).WithAlias(() => orderSummary.Id)) 
      .Add(Projections.Property(() => orderAlias.Status).WithAlias(() => orderSummary.Status) 
    ); 
Result = query.TransformUsing(Tranformers.AliasToBean<OrderSummary>()) 
    .List<OrderSummary>() 
    .ToList(); 
+0

はこちらをご覧ください:https://stackoverflow.com/questions/29644236/use-nhibernate-aliastobean-transformer-launch-n1-クエリ –

+0

私はあなたがそこに投稿したリンクは、コメントに入れられた解決策を使用しています: 'var query = session.QueryOver () .SelectList(list => ).Select(Projections.Property(" OrderStatus "結果はOKですが、jsonがクライアントに送信されるOrderにはOrderStatusプロパティが含まれていますが、プロパティにはメタデータのみが含まれており、プロパティの実際の値は含まれていません。 – Bunnynut

+0

プロキシーを意味しますか?この場合、Statusプロパティのlazyloadingを無効にしてください。 –

答えて

1

申し訳ありません申し訳ありませんあなたの前例を尋ねるコメントは表示されませんでした。 それは既に他の応答での代替として与えられたが、私は、私が述べたアプローチを説明するいくつかのコードを残すつもりだと私はそれが(すべてで変圧器を使用していない)に行くための最も簡単な方法だと考えている:

string GetOrderSummaries() 
{ 
    // First, you just query the orders and eager fetch the status. 
    // The eager fetch is just to avoid a Select N+1 when traversing the returned list. 
    // With that, we make sure we will execute only one query (it will be a join). 
    var query = session.QueryOver<Order>() 
         .Fetch(o => o.Status).Eager; 

    // This executes your query and creates a list of orders. 
    var orders = query.List(); 

    // We map these orders to DTOs, here I'm doing it manually. 
    // Ideally, have one DTO for Order (OrderSummary) and one for OrderStatus (OrderSummaryStatus). 
    // As mentioned by the other commenter, you can use (for example) AutoMapper to take care of this for you: 
    var orderSummaries = orders.Select(order => new OrderSummary 
    { 
     Id = order.Id, 
     Status = new OrderSummaryStatus 
     { 
     Id = order.Status.Id, 
     Name = order.Status.Name 
     } 
    }).ToList(); 

    // Yes, it is true that this implied that we not only materialized the entities, but then went over the list a second time. 
    // In most cases I bet this performance implication is negligible (I imagine serializing to Json will possibly be slower than that). 
    // And code is more terse and possibly more resilient. 

    // We serialize the DTOs to Json with, for example, Json.NET 
    var orderSummariesJson = JsonConvert.SerializeObject(orderSummaries); 
    return orderSummariesJson; 
} 

便利なリンク:
AutoMapper:http://automapper.org/
Json.NET:http://www.newtonsoft.com/json

2

。私は、Nhibernateトランスフォーマーはネストされた複雑なプロパティを構築できないと思います。 あなたはタプルのリストを返し、その後、あなたのエンティティに手動でそれをキャストすることができます:あなたは多くのパフォーマンスについて気にしない場合

OrderStatus statusAlias = null;   

var tuples = Session.QueryOver<Order>() 
      .JoinQueryOver(x => x.Status,() => statusAlias) 
      .SelectList(list => list 
       .Select(x => x.Id) 
       .Select(x => statusAlias.Id) 
       .Select(x => statusAlias.Name)) 
      .List<object[]>(); 

var result = tuples.Select(Convert); 

private OrderSummary Convert(object[] item) { 
      return new OrderSummary 
      { 
       Id = (long)item[0], 
       OrderStatus = new OrderStatus { Id = (long)item[1], Name = (string)item[2] } 
      }; 
     } 

はまた、それはあなたの注文のリストを取得し、OrderSummaryに変換することが可能です。キャスト演算子を定義するか、AutoMapperまたはExpressMapperのようなツールを使用するだけで簡単に実行できます。

関連する問題