开发者

How to use LINQ to query from a list of objects into an existing object?

I'm not sure if this is possible in LINQ, but I have the following scenario:

I'm calling a SharePoint list service multiple times with multiple queries. I am then populating a single object and its properties from all of the queries. I am using LINQ to query the XElement returned. I know that if the call gets to this point, that there will only ever be one item returned from my LINQ query. I currently have to query into a new object and then set the properties of my main object from this new object (from LINQ), for each web service call. (The below code sample contains only a small portion of the 'Action' item properties that would need to b开发者_如何转开发e queried and set.)

Is there any way to make the below statement 'select' into my existing 'action' object?

var item = (from listItem in result.GetSPListItems()
            select new ContractAction
            {
                Title = listItem.GetSPFieldValue("Title"),
                Description = listItem.GetSPFieldValue("Description"),
                DeliveryOrderID = SPHelper.GetFirstLookupID(listItem.GetSPFieldValue("Delivery Order")),
                EstimatedValue = ((listItem.GetSPFieldValue("Estimated Value") as double?) ?? 0),
                AgreementTypeID = SPHelper.GetFirstLookupID(listItem.GetSPFieldValue("Contract Type")),                                                
            }).FirstOrDefault();

contractAction.Title = item.Title;
contractAction.Description = item.Description;
contractAction.DeliveryOrderID = item.DeliveryOrderID;
contractAction.EstimatedValue = item.EstimatedValue;
contractAction.AgreementTypeID = item.AgreementTypeID;


Can't you simply:

action = (from listItem in result.GetSPListItems()
         select new Action
         {
             Title = listItem.GetSPFieldValue("Title"),
             Description = listItem.GetSPFieldValue("Description"),
             DeliveryOrderID = SPHelper.GetFirstLookupID(listItem
                 .GetSPFieldValue("Delivery Order")),
             EstimatedValue = 
                 ((listItem.GetSPFieldValue("Estimated Value") as double?) ?? 0),
             AgreementTypeID = SPHelper.GetFirstLookupID(listItem
                 .GetSPFieldValue("Contract Type")),
         }).FirstOrDefault();


Firstly you should rename the class Action because Action is a defined delegate in the built-in library. I'll use MyAction in the following code.

And if you always need to get MyAction from SPListItem, you'd better write a extension method to put the logic in one place for DRY(Don't Repeat Yourself).

public static MyAction ToMyAction(this SPListItem item)
{
    return new MyAction  
       {  
          Title = item.GetSPFieldValue("Title"),  
          Description = item.GetSPFieldValue("Description"),  
          DeliveryOrderID = SPHelper.GetFirstLookupID(item.GetSPFieldValue("Delivery Order")),  
          EstimatedValue = ((item.GetSPFieldValue("Estimated Value") as double?) ?? 0),  
          AgreementTypeID = SPHelper.GetFirstLookupID(item.GetSPFieldValue("Contract Type"))                                                  
       };  
}

var action = result.GetSPListItems()
                   .Select(item => item.ToMyAction())
                   .FirstOrDefault();
//var action = (from item in result.GetSPListItems()
//              select item.ToMyAction()).FirstOrDefault();


First, since I know I'm only going to have one result I just had to be willing to remove the idea of using the 'select' part of a linq query. Once I did that, the answer was obvious.

//just grab the first item
var item = result.GetSPListItems().FirstOrDefault();

//then grab the properties into the existing ContractActionEntity                             
contractAction.Title = item.GetSPFieldValue("Title");
contractAction.Description = item.GetSPFieldValue("Description");
contractAction.DeliveryOrderID = SPHelper.GetFirstLookupID(item.GetSPFieldValue("Delivery Order"));
contractAction.EstimatedValue = item.GetSPFieldValue("Estimated Value").ToNullableDouble();
contractAction.AgreementTypeID = SPHelper.GetFirstLookupID(item.GetSPFieldValue("Contract Type")),

Thanks everyone for making me think more about the problem and leading me in the direction of the answer.


You could write your queries in one big query. So for example you could have:

var item = (from listItem in result.GetSPListItems()
        from query2Outer in result.SecondQuery().Where(x => x.ItemEdp == it.ItemEdp).DefaultIfEmpty() // This is an outer join
        select new Action
        {
            //if the one query didn't return an item then it sets the properties to the default values
            Example = (query2Outer == null ? "Default Value" : query2Outer.Example),
            Title = listItem.GetSPFieldValue("Title"),
            Description = listItem.GetSPFieldValue("Description"),
            DeliveryOrderID = SPHelper.GetFirstLookupID(listItem.GetSPFieldValue("Delivery Order")),
            EstimatedValue = ((listItem.GetSPFieldValue("Estimated Value") as double?) ?? 0),
            AgreementTypeID = SPHelper.GetFirstLookupID(listItem.GetSPFieldValue("Contract Type")),                                                
        }).FirstOrDefault();


An alternative to the extension methods approach would be:

public static void SelectFirstInto(this IEnumerable<ContractAction> items, ContractAction target)
{
    var source = items.FirstOrDefault();

    if(source != null)
    {
        target.Title = source.Title,  
        target.Description = source.Description ,  
        target.DeliveryOrderID = source.DeliveryOrderID,  
        target.EstimatedValue = source.EstimatedValue, 
        target.AgreementTypeID = source.AgreementTypeID                                                 
     }
}

Then you could do:

ContractAction targetAction = new ContractAction();
var item = (from listItem in result.GetSPListItems()
            select new ContractAction
            {
                Title = listItem.GetSPFieldValue("Title"),
                Description = listItem.GetSPFieldValue("Description"),
                DeliveryOrderID = SPHelper.GetFirstLookupID(listItem.GetSPFieldValue("Delivery Order")),
                EstimatedValue = ((listItem.GetSPFieldValue("Estimated Value") as double?) ?? 0),
                AgreementTypeID = SPHelper.GetFirstLookupID(listItem.GetSPFieldValue("Contract Type")),                                                
            }).SelectFirstInto(targetAction);

Keep in mind that if the list is empty, then the target object remains unmodified. This may be something you'll want to handle accordingly.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜