How can I set a value on a Linq object during the

2019-04-11 11:41发布

问题:

I have a simple query as shown below

var trips = from t in ctx.Trips
            select t;

The problem is that I have an extra property on the Trip object that needs to be assigned, preferably without iterating through the returned IQueryable.

Does anyone know how to set the value during the query? (i.e. select t, t.property = "value")

回答1:

First of all, if you never iterate through the results, your code won't run. LINQ is "lazy", meaning that it only computes the next result when you ask for it.

However, if you do really need to do what you ask, try something like this:

Trip SetProperty(Trip t)
{
    t.property = "value";
    return t;
}
var trips = from t in ctx.Trips select SetProperty(t);


回答2:

This would work:

var trips = from t in ctx.Trips select new Trip 
{
    // db properties
    t.ID,
    t.Name,
    t.Description,

    // non-db properties
    SomeValue = 45,
    SomeOtherValue = GetValueFromSomewhereInCode(t.ID)
}

By projecting your database rows into 'new' Trip objects you can set properties that are not populated by LINQ to SQL, without any additional enumeration required. You can also call custom code in your projection because it executes in code, and not as part of the SQL statement sent to the database.

However, the resulting Trip objects are not enabled for change-tracking so bear that in mind (you can't make changes to properties and have them automatically updated via SubmitChanges(), because the data context doesn't know about your Trip objects).

If you need to track changes as well then you will need to enumerate the tracked Trip objects again after you have retrieved them via LINQ to SQL. This isn't really a problem though as it should be an in-memory iteration.



回答3:

If you don't want to iterate through the sequence of Trips, you are better of directly updating the database using a stored procedure or parameterized query.

If you're worried that the Trips sequence will contain too many items and be slow to process, you could of course add more filtering in the where clause.

If this isn't possible, it's just another reason to do the processing of very large result sets on the database using a stored proc etc.

Otherwise the usual LINQ to SQL approach is something like:

using (var context = new DefaultDataContext())
{
    var defects = context.Defects.Where(d => d.Status==Status.Open);             

    foreach(Defect d in defects)
    {
        defect.Status = Status.Fixed;                     
        defect.LastModified = DateTime.Now;
    }
    context.SubmitChanges();                 
}