简体   繁体   中英

how can I reduce 2 select to 1 select linq to gain performance?

my question is simple but I got stuck with something. Can you tell me how can I reduce 2 select into 1 select LINQ in c#? I am using CloudNative.CloudEvents NuGet package for cloud-native events.

var orderEvents = input
    .Select(_ => new OrderDocument(_.Id, _.ToString()).ToOrderEvent())
    .Select(_ =>
        new CloudEvent()
        {
            Type = _.EventType,
            Subject = _.Subject,
            Source = _.Source,
            Data = _
        });

input is a parameter from cosmosDbTrigger it`s type : IReadOnlyList

OrderDocument.cs

public class OrderDocument
{
    public string Id { get; private set; }

    public string Json { get; private set; }

    public OrderDocument(string id, string json)
    {
        Id = id;
        Json = json;
    }

    public OrderEvent ToOrderEvent() => OrderEventHelper.ToOrderEvent(Json);
}

OrderEventHelper.cs

public static OrderEvent ToOrderEvent(string json)
{
    ArgumentHelper.ThrowIfNullOrEmpty(json);

    var orderEvent = JsonConvert.DeserializeObject<OrderEvent>(json);
    var eventDefinition = OrderEvents.EventDefinitions.SingleOrDefault(_ => _.EventType == orderEvent.EventType);

    
    return eventDefinition == null
        ? orderEvent
        : new OrderEvent(
            orderEvent.Id,
            orderEvent.Source,
            orderEvent.EventType,
            orderEvent.Subject,
            orderEvent.DataContentType,
            orderEvent.DataSchema,
            orderEvent.Timestamp,
            JsonConvert.DeserializeObject(orderEvent.Payload.ToString(), eventDefinition.PayloadType),
            orderEvent.TraceId);

}

linq extensions are basically for loops in the background. If you want to perform multiple actions against a list, perhaps making your own simple for loop where you can manage that yourself would work.

Your code:

var orderEvents = input
    .Select(_ => new OrderDocument(_.Id, _.ToString()).ToOrderEvent())
    .Select(_ =>
        new CloudEvent()
        {
            Type = _.EventType,
            Subject = _.Subject,
            Source = _.Source,
            Data = _
        });

could be changed to:

// our result set, rather than the one returned from linq Select
var results = new List<CloudEvent>();

foreach(var x in input){
   // create the order event here
   var temporaryOrderEvent = new OrderDocument(x.Id, x.ToString()).ToOrderEvent();
   
   // add the Cloud event to our result set
   results.Add(new CloudEvent() 
   {
       Type = temporaryOrderEvent .EventType,
       Subject = temporaryOrderEvent .Subject,
       Source = temporaryOrderEvent .Source,
       Data = temporaryOrderEvent 
   });
}

where you then have a result list to work with.

If you wanted to keep it all in linq, you could instead perform all of your logic in the first Select , and ensure that it returns a CloudEvent . Notice here that you can employ the use of curly brackets in the linq statement to evaluate a function rather than a single variable value:

var orderEvents = input
    .Select(x => 
    {
       // create the order event here
       var temporaryOrderEvent = new OrderDocument(x.Id, x.ToString()).ToOrderEvent();

       // return the Cloud event here
       return new CloudEvent() 
                  {
                       Type = temporaryOrderEvent .EventType,
                       Subject = temporaryOrderEvent .Subject,
                       Source = temporaryOrderEvent .Source,
                       Data = temporaryOrderEvent 
                  };
    });

How about putting conversion to OrderEvent and using ToCloudEvent in the same Select?

var orderEvents = input
    .Select(_ => new OrderDocument(_.Id, _.ToString()).ToOrderEvent().ToCloudEvent())


public class OrderEvent
{
    public CloudEvent ToCloudEvent()
    {
        new CloudEvent()
        {
            Type = this.EventType,
            Subject = this.Subject,
            Source = this.Source,
            Data = this
        };
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM