开发者

How can i pass a Lazy<T> into my projection?

开发者 https://www.devze.com 2023-02-20 06:24 出处:网络
My Vehicle type: public class Vehicle : EntityObject { private Lazy<string> _nameFromDelegate = null;

My Vehicle type:

public class Vehicle : EntityObject
{
    private Lazy<string> _nameFromDelegate = null;
    private Lazy<IList<Component>> _components = null;


    public Vehicle(int id, string name, Lazy<string> nameFromDelegate, Lazy<IList<Component>> components)
        : base(id)
    {
        this.Name = name;
        this._nameFromDelegate = nameFromDelegate;
    }


    public string Name { get; private set; }
    public string NameFromDelegate
    {
        get
        {
            return this._nameFromDelegate.Value;
        }
    }

    public IList<Component> Components
    {
        get
        {
            return this._components.Value;
        }
    }
}

I want to project my type in L2S using the constructor and pass in certain mappings as delegates so they're evaluated in memory rather than L2S trying to translate them to SQL.

In the example below i'm trying to map the "vehicle.Name" value from SQL onto two properties on my Vehicle type: the "Name" string property and the "NameFromDelegate" string property (which encapsulates the Lazy<string>).

I'm hoping to prove that it doesn't make any difference to L2S whether i pass in the "vehicle.Name" to the string ctor param or to the Lazy<string> ctor param. But perhaps it does:

How can i pass a Lazy<T> into my projection?

I don't understand why there is a need to cast from string to Func<string>. Ideas?

Stack trace for reference:

   at System.Convert.DefaultToType(IConvertible value, Type targetType, IFormatProvider provider)
   at System.String.System.IConvertible.ToType(Type type, IFormatProvider provider)
   at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
   at System.Data.Linq.DBConvert.ChangeType(Object value, Type type)
   at Read_Vehicle(ObjectMaterializer`1 )
   at System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReader`2.MoveNext()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at DelegateQueries.Models.V开发者_JAVA百科ehicleRepoWithDelegates.GetAll() in %path%\DelegateQueries\Models\VehicleRepoWithDelegates.cs:line 26
   at DelegateQueries.Tests.RepoTests.VehicleRepo_CanReturn_NameFromDelegateProp_InLinq_WithDelegate() in %path%\DelegateQueries\DelegateQueries.Tests\RepoTests.cs:line 31


This appears to work around the problem:

static Lazy<T> Lazyfy<T>(T input)
{
    return new Lazy<T>(() => input);
}

public IQueryable<Vehicle> Vehicles()
{
    return from veh in ctx.vehicles
           select new Vehicle(veh.id, veh.name, Lazyfy(veh.name), null);
}

UPDATE you can also do this:

static Func<T> Functify<T>(T input)
{
    return () => input;
}

public IQueryable<Vehicle> Vehicles()
{
    return from veh in ctx.vehicles
           select new Vehicle(veh.id, veh.name, new Lazy<string>(Functify(veh.name)), null);
}

but you can't do this:

var r = from veh in ctx.vehicles
                    select new Func<int>(() => veh.id);
r.ToList();

It appears that L2S is treating the lambda expression creation as a value assignment, instead as a method call and is trying to convert the value from the db to it. I'm saying it's a bug since this works on linq to objects.

0

精彩评论

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

关注公众号