2013-12-13 48 views
0

我遇到了使用下面的代碼將實體框架6模型轉換爲Dto的問題。在閱讀 CodeProject article by Sacha Barber後,我已經使用這種將實體轉換爲Dtos的方法多次。該代碼昨天晚上正在工作,所以今天早上模型的更改可能會影響代碼。在Linq中將實體框架模型轉換爲Dto

只需注意layoutTransator對象從Unity IoC容器中正確加載。

我已閱讀this Stackoverflow question但它並沒有真正覆蓋我的問題。

實體模型

enter image description here

加載實體框架模型

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到對象即

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

感謝詹姆斯。這爲我解決了問題。不知道它以前如何工作。 –

+0

@PhilMurray不用擔心,也許你之前有過一個'ToList'的調用,這意味着這個集合已經從DB中被拉下來了? – James

+0

可能。不記得了,我已經睡過了,因爲:-) –