2015-06-12 17 views
5

Tôi đang cố gắng để chọn kỷ lục mới nhất trong một bộ sưu tập cho từng nhóm theo một phím đa lĩnh vực, sử dụng giao diện tổng hợp thông thạo:Mongo C# driver 2.0 tổng hợp Nhóm ngoại lệ

 var matches = await Collection.Aggregate() 
      .Match(x => x.EffectiveDate >= minEffectiveDate) 
      .SortByDescending(x => x.LastUpdate) 
      .Group(key => new { key.EffectiveDate, key.ProductOid, key.InstrumentParentOid, key.ComponentOid, key.EventSummary }, g => g.First()) 
      .ToListAsync(); 

Tuy nhiên, tôi nhận được ngoại lệ sau:

System.InvalidCastException occurred 
    HResult=-2147467262 
    Message=Unable to cast object of type 'MongoDB.Driver.Linq.Expressions.SerializationExpression' to type 'System.Linq.Expressions.MethodCallExpression'. 
    Source=MongoDB.Driver 
    StackTrace: 
    at MongoDB.Driver.Linq.Processors.GroupSerializationInfoBinder.GetBodyFromSelector(MethodCallExpression node) 
    at MongoDB.Driver.Linq.Processors.GroupSerializationInfoBinder.GetAggregationArgument(MethodCallExpression node) 
    at MongoDB.Driver.Linq.Processors.GroupSerializationInfoBinder.VisitMethodCall(MethodCallExpression node) 
    at MongoDB.Driver.Linq.Translators.AggregateProjectionTranslator.BindSerializationInfo(SerializationInfoBinder binder, LambdaExpression node, IBsonSerializer parameterSerializer) 
    at MongoDB.Driver.Linq.Translators.AggregateProjectionTranslator.TranslateGroup[TKey,TDocument,TResult](Expression`1 idProjector, Expression`1 groupProjector, IBsonSerializer`1 parameterSerializer, IBsonSerializerRegistry serializerRegistry) 
    at MongoDB.Driver.IAggregateFluentExtensions.GroupExpressionProjection`3.Render(IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry) 
    at MongoDB.Driver.AggregateFluent`2.<>c__DisplayClass1`1.<Group>b__0(IBsonSerializer`1 s, IBsonSerializerRegistry sr) 
    at MongoDB.Driver.DelegatedPipelineStageDefinition`2.Render(IBsonSerializer`1 inputSerializer, IBsonSerializerRegistry serializerRegistry) 
    at MongoDB.Driver.PipelineStageDefinition`2.MongoDB.Driver.IPipelineStageDefinition.Render(IBsonSerializer inputSerializer, IBsonSerializerRegistry serializerRegistry) 
    at MongoDB.Driver.PipelineStagePipelineDefinition`2.Render(IBsonSerializer`1 inputSerializer, IBsonSerializerRegistry serializerRegistry) 
    at MongoDB.Driver.MongoCollectionImpl`1.<AggregateAsync>d__7`1.MoveNext() 
--- End of stack trace from previous location where exception was thrown --- 
    at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
    at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
    at MongoDB.Driver.IAsyncCursorSourceExtensions.<ToListAsync>d__14`1.MoveNext() 

Ok. Vì vậy, nó không giống như phương pháp mở rộng IEnumerable vì lý do nào đó. Vì vậy, tôi cố gắng trích xuất các phương pháp khuyến nông LINQ:

 var matches = await Collection.Aggregate() 
      .Match(x => x.EffectiveDate >= minEffectiveDate) 
      .SortByDescending(x => x.LastUpdate) 
      .Group(key => new { key.EffectiveDate, key.ProductOid, key.InstrumentParentOid, key.ComponentOid, key.EventSummary }, g => g) 
      .ToListAsync(); 
     return matches.Select(x => x.First()); 

Nhưng:

System.InvalidCastException occurred 
    HResult=-2147467262 
    Message=Unable to cast object of type 'MongoDB.Bson.Serialization.Serializers.ArraySerializer`1[SPMO.Providers.Audit.Messages.ProductAdjustmentAuditDataDb]' to type 'MongoDB.Bson.Serialization.IBsonSerializer`1[System.Linq.IGrouping`2[<>f__AnonymousType0`5[System.Nullable`1[System.DateTime],System.Nullable`1[System.Int32],System.Nullable`1[System.Int32],System.Nullable`1[System.Int32],System.String],SPMO.Providers.Audit.Messages.ProductAdjustmentAuditDataDb]]'. 
    Source=MongoDB.Driver 
    StackTrace: 
     at MongoDB.Driver.Linq.Translators.AggregateProjectionTranslator.TranslateGroup[TKey,TDocument,TResult](Expression`1 idProjector, Expression`1 groupProjector, IBsonSerializer`1 parameterSerializer, IBsonSerializerRegistry serializerRegistry) 
     at MongoDB.Driver.IAggregateFluentExtensions.GroupExpressionProjection`3.Render(IBsonSerializer`1 documentSerializer, IBsonSerializerRegistry serializerRegistry) 
     at MongoDB.Driver.AggregateFluent`2.<>c__DisplayClass1`1.<Group>b__0(IBsonSerializer`1 s, IBsonSerializerRegistry sr) 
     at MongoDB.Driver.DelegatedPipelineStageDefinition`2.Render(IBsonSerializer`1 inputSerializer, IBsonSerializerRegistry serializerRegistry) 
     at MongoDB.Driver.PipelineStageDefinition`2.MongoDB.Driver.IPipelineStageDefinition.Render(IBsonSerializer inputSerializer, IBsonSerializerRegistry serializerRegistry) 
     at MongoDB.Driver.PipelineStagePipelineDefinition`2.Render(IBsonSerializer`1 inputSerializer, IBsonSerializerRegistry serializerRegistry) 
     at MongoDB.Driver.MongoCollectionImpl`1.<AggregateAsync>d__7`1.MoveNext() 
    --- End of stack trace from previous location where exception was thrown --- 
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
     at MongoDB.Driver.IAsyncCursorSourceExtensions.<ToListAsync>d__14`1.MoveNext() 
    --- End of stack trace from previous location where exception was thrown --- 
     at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
     at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
     at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 

Kế hoạch của tôi B chỉ là để quên đi tổng hợp, làm một Find đơn giản() và sau đó làm một groupby() trong vani LINQ, nhưng tôi muốn làm việc này trên DB vì nó sẽ hiệu quả hơn.

+1

bạn đã thử một loại tên ở vị trí của loại vô danh? – lobsterism

+0

Cảm ơn bạn đã đề xuất. Tôi đã đăng qua nhóm người dùng MongoDB C# Google tại đây - https://groups.google.com/forum/#!topic/mongodb-csharp/nmSYSiyBzOo - có vẻ như đang thực hiện .First() trên toàn bộ đối tượng không được hỗ trợ ; bạn phải định nghĩa một phép chiếu. Tôi đang đi với kế hoạch của tôi B cho bây giờ. – ultra909

Trả lời

4

Tôi đã chạy trên cùng một vấn đề. Cách giải quyết của tôi khác: thay vì sử dụng phía khách hàng LINQ GroupBy(), tôi thực hiện hai cuộc gọi máy chủ.

  1. Lấy các đối tượng MongoDB của tài liệu tôi muốn truy xuất, tức là các tài liệu tôi muốn Nhóm() chỉ đơn giản là phát ra cho tôi như POCO.
  2. Thực hiện Find() với Chứa() so với bộ sưu tập của ObjectIds từ bước 1.

Mã chứng minh điều này

public static class WidgetWorker 
{ 
    public static void Main() 
    { 
     //setup 
     var widgetCollection = new MongoClient("mongodb://localhost:27017") 
      .GetDatabase("WidgetDatabase") 
      .GetCollection<Widget>("Widget"); 
     widgetCollection.DeleteManyAsync(x => true).Wait(); //remove all existing rows 

     //create widgets and add to DB; 2 SKUs, each with multiple revisions 
     var widgetA1 = new Widget() { SKU = "aaaa", Revision = 1M, Cost = 10 }; 
     var widgetA2 = new Widget() { SKU = "aaaa", Revision = 2.1M, Cost = 20 }; 
     var widgetA3 = new Widget() { SKU = "aaaa", Revision = 2.2M, Cost = 30 }; 
     var widgetB1 = new Widget() { SKU = "bbbb", Revision = 1M, Cost = 40 }; 
     var widgetB2 = new Widget() { SKU = "bbbb", Revision = 1.1M, Cost = 50 }; 
     widgetCollection.InsertManyAsync(new[] { widgetA1, widgetA2, widgetA3, widgetB1, widgetB2 }).Wait(); 

     //get the ObjectId of the most Recent revision of each SKU 
     var r = widgetCollection 
      .Aggregate() 
      .SortByDescending(x => x.Revision) 
      .Group(x => x.SKU, g => new { Id = g.First().Id }) 
      .ToListAsync() 
      .Result; 

     //get the Widget objects for the list of ids just collected 
     var ids = r.Select(x => x.Id).ToArray(); 
     var widgets = widgetCollection 
      .Find(x => ids.Contains(x.Id)) 
      .ToListAsync() 
      .Result; 

     //check results 
     Debug.Assert(widgets.Count() == 2); 
     Debug.Assert(widgets.Single(x => x.SKU == "aaaa").Revision == 2.2M); 
     Debug.Assert(widgets.Single(x => x.SKU == "bbbb").Revision == 1.1M); 
    } 
} 

public class Widget 
{ 
    [BsonId] 
    public ObjectId Id { get; set; } 
    public string SKU { get; set; } 
    public decimal Revision { get; set; } 
    public decimal Cost { get; set; } 
} 
+0

Điều này gần như chắc chắn sẽ là một cách tiếp cận hiệu quả hơn với một tập hợp kết quả lớn và/hoặc các đối tượng lớn. Cảm ơn. – ultra909

Các vấn đề liên quan