Как я могу передать Lazy <T>в мою проекцию? - PullRequest
4 голосов
/ 29 марта 2011

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

Я хочу проецировать свой тип в L2S с использованием конструктора и передавать определенные отображения в качестве делегатов, чтобы они оценивались в памяти, а не в L2S, пытаясь их перевестив SQL.

В приведенном ниже примере я пытаюсь отобразить значение «vehicle.Name» из SQL на два свойства моего типа Vehicle: свойство «Name» string и «NameFromDelegate» string свойство (которое инкапсулирует Lazy<string>).

Я надеюсь доказать, что для L2S не имеет значения, передам ли я "vehicle.Name" параметру string ctorили к параметру Lazy<string> ctor.Но, возможно, так оно и есть: enter image description here

Я не понимаю, почему необходимо разыгрывать от string до Func<string>.Идеи?

Трассировка стека для справки:

   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.VehicleRepoWithDelegates.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

1 Ответ

2 голосов
/ 29 марта 2011

Похоже, что для решения проблемы:

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

ОБНОВЛЕНИЕ Вы также можете сделать это:

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

но вы не можете сделать это:

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

Похоже, что L2S рассматривает создание лямбда-выражения как присвоение значения, а не как вызов метода и пытается преобразовать значение из базы данных в него. Я говорю, что это ошибка, так как это работает на linq для объектов.

...