【问题标题】:Translating Entity Framework Model to Dto in Linq在 Linq 中将实体框架模型转换为 Dto
【发布时间】:2013-12-13 10:18:25
【问题描述】:

我在使用以下代码将 Entity Framework 6 模型转换为 Dto 时遇到问题。在阅读a之后,我已经多次使用这种将实体转换为Dtos的方法 CodeProject article by Sacha Barber。代码昨晚还在工作,所以今天早上对模型的更改可能影响了代码。

请注意 layoutTransator 对象已从 Unity IoC 容器正确加载。

我已经查看了this Stackoverflow question ,但它并没有真正涵盖我的问题。

实体模型

加载实体框架模型

    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

【问题讨论】:

    标签: c# .net entity-framework linq-to-entities dto


    【解决方案1】:

    您只需要更改调用TranslateDto 方法的上下文。目前,您告诉 L2E,此方法将在 DB 端运行,但是,您的方法无法转换为 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)));
    

    【讨论】:

    • 谢谢詹姆斯。这为我解决了这个问题。不知道它以前是如何工作的。
    • @PhilMurray 不用担心,也许您之前曾致电ToList,这意味着该集合已从数据库中删除?
    • 可能。不记得了,自从做了之后我就睡了:-)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    • 2021-12-16
    • 2019-04-22
    • 1970-01-01
    • 2013-06-04
    • 2018-09-14
    • 1970-01-01
    相关资源
    最近更新 更多