2013-12-13 3 views
0

У меня возникла проблема с переводом модели Entity Framework 6 на Dto с приведенным ниже кодом. Я использовал этот метод преобразования сущностей в Dtos несколько раз после чтения CodeProject article by Sacha Barber. Код работал вчера вечером, поэтому, возможно, изменение модели сегодня утром повлияло на код.Перевод модели структуры сущностей в Dto в Linq

Просто отметить, что объект layoutTransator правильно загружен из контейнера Unity IoC.

Я рассмотрел this Stackoverflow question, но на самом деле это не касается моей проблемы.

Entity Model

enter image description here

Загрузка Entity Framework модель

private readonly PortalEntities ctx; 
    private readonly IEntityDtoTranlator<Layout, LayoutsDto> layoutTranslator; 

    [InjectionConstructor] 
    public Dal(IContextFactory<JcbManufacturingPortalEntities> factory, 
        IEntityDtoTranlator<Layout, LayoutsDto> layoutTransator)) 
    { 
     ctx = factory.Create(ConfigurationManager.ConnectionStrings[EntityConnection].ConnectionString, EntityPassword); 
     this.layoutTranslator = layoutTransator; 
    } 

    public List<LayoutsDto> GetDiplayLayouts(string machineAssetName) 
    { 
     try 
     { 
      return (ctx.Layouts.Where(m => m.Hardware.AssetName.Equals(machineAssetName)) 
         .Select(l => layoutTranslator.TranslatetoDto(l))).ToList(); 
     } 
     catch (Exception ex) 
     { 

      throw; 
     }  

    } 

Если я разрушу код нагрузки, как показано ниже он работает. Должна быть проблема с вызовом метода Linq.

List<Layout> layout = (ctx.Layouts.Where(m => m.Hardware.AssetName.Equals(machineAssetName))).ToList(); 
LayoutsDto dto = layoutTranslator.TranslatetoDto(layout.First()); 

Dto

public class LayoutsDto 
{ 
    [Key] 
    public int ID { get; set; } 

    [DefaultValue(0)] 
    [Range(0,3600000)] 
    public int Duration { get; set; } 

    [DefaultValue(0)] 
    public bool OutOfShift { get; set; } 

    public byte FlipOrder { get; set; } 

    public List<ScreenDto> Screens { get; set; } 
} 

Преобразователь

internal class LayoutTranslator<TEntity, TDto> : IEntityDtoTranlator<Layout, LayoutsDto> 
{ 
    public LayoutsDto TranslatetoDto(Layout entity) 
    { 
     return new LayoutsDto 
     { 
      Duration = entity.DisplayDuration, 
      FlipOrder = entity.FlipOrder, 
      ID = entity.ID, 
      OutOfShift = entity.IsOutOfShiftScreen 
     }; 
    } 

    public Layout TranslateToEntity(LayoutsDto dto) 
    { 
     return new Layout 
     { 
      DisplayDuration = dto.Duration, 
      FlipOrder = dto.FlipOrder, 
      ID = dto.ID, 
      IsOutOfShiftScreen = dto.OutOfShift 
     }; 
    } 
} 

Исключение

Одна точка является то, что TranslatetoDto(Jmp.Andon.Service.Data.Layout) метод не в Jmp.Andon.Models.LayoutsDto объекта

LINQ to Entities does not recognize the method 'Jmp.Andon.Models.LayoutsDto TranslatetoDto(Jmp.Andon.Service.Data.Layout)' method, and this method cannot be translated into a store expression. 

    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.DefaultTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, DbExpression& source, DbExpressionBinding& sourceBinding, DbExpression& lambda) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SequenceMethodTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, SequenceMethod sequenceMethod) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TypedTranslator`1.Translate(ExpressionConverter parent, Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) 
    at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.Convert() 
    at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption) 
    at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClassb.<GetResults>b__a() 
    at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction[T](Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess) 
    at System.Data.Entity.Core.Objects.ObjectQuery`1.<>c__DisplayClassb.<GetResults>b__9() 
    at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation) 
    at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) 
    at System.Data.Entity.Core.Objects.ObjectQuery`1.<System.Collections.Generic.IEnumerable<T>.GetEnumerator>b__0() 
    at System.Lazy`1.CreateValue() 
    at System.Lazy`1.LazyInitValue() 
    at System.Lazy`1.get_Value() 
    at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext() 
    at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) 
    at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) 
    at Jmp.Andon.Service.Data.Dal.GetDiplayLayouts(String machineAssetName) in c:\Perforce\Development\JMP v2\Jmp.Display\Jmp.Display.Service\Data\Dal.cs:line 38 

ответ

1

Вам просто нужно изменить контекст, в котором ваш метод TranslateDto который вызывается. На данный момент вы сообщаете L2E, что этот метод будет запущен на стороне БД, однако ваш метод не переводится на SQL и поэтому не может быть выполнен таким образом.

Вы должны заставить запрос выполнить этот метод на клиента и делать, что вам нужно переключить запрос из L2E в LINQ To Objects т.е.

return (ctx.Layouts.Where(m => m.Hardware.AssetName.Equals(machineAssetName)) 
        .AsEnumerable() // <-- Here's the switch 
        .Select(l => layoutTranslator.TranslatetoDto(l))); 
+0

Спасибо Джеймс. Это очистило проблему для меня. Не знаю, как это работает. –

+0

@PhilMurray не беспокоится, возможно, у вас был вызов 'ToList', прежде чем это означало, что коллекция уже была вытащена из БД? – James

+0

возможно. Не могу вспомнить, я спал с тех пор :-) –

Смежные вопросы