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

Time:06-28

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);

}

CodePudding user response:

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 
                  };
    });

CodePudding user response:

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
        };
    }
}
  • Related