ExpressMapper / EntityFramework - 没有为此对象定义无参数构造函数

Posted

技术标签:

【中文标题】ExpressMapper / EntityFramework - 没有为此对象定义无参数构造函数【英文标题】:ExpressMapper / EntityFramework - No parameterless constructor defined for this object 【发布时间】:2016-10-26 01:16:14 【问题描述】:

我正在尝试使用 ExpressMapper 将数据实体映射到模型。

如果我直接将实体映射到模型(它们都具有相同的属性),那么它工作正常。

但是,如果我将链接实体映射到模型,则会出现错误

出现错误:System.MissingMethodException:否 为此对象定义的无参数构造函数。

数据库结构:

ExpressMapper 注册:

Mapper.Register<DiscountDaysOfWeek, DiscountDaysOfWeekModel>()
      .Member(dest => dest.DiscountDayId, src => src.DiscountDayId)
      .Member(dest => dest.DiscountDaysOfWeekId, src => src.DiscountDaysOfWeekId)
      .Member(dest => dest.DiscountId, src => src.DiscountId)
      .Member(dest => dest.Discountday, src => src.DiscountDay.Day);

这样调用:

var disDays = discs.SelectMany(x => x.DiscountDaysOfWeeks)
                   .Map<IQueryable<DiscountDaysOfWeek>, IQueryable<DiscountDaysOfWeekModel>>();

在调用时获取错误消息。

DiscountDaysOfWeekModel:

public class DiscountDaysOfWeekModel

    public int DiscountDaysOfWeekId  get; set; 
    public int DiscountId  get; set; 
    public int DiscountDayId  get; set; 
    public string Discountday  get; set; 

DiscountDayOfWeek(由 EF 生成)

public partial class DiscountDaysOfWeek

    public int DiscountDaysOfWeekId  get; set; 
    public int DiscountId  get; set; 
    public int DiscountDayId  get; set; 

    public virtual DiscountDay DiscountDay  get; set; 
    public virtual Discount Discount  get; set; 

DiscountDay(由EF生成):

public partial class DiscountDay

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public DiscountDay()
    
        this.DiscountDaysOfWeeks = new HashSet<DiscountDaysOfWeek>();
    

    public int DiscountDayId  get; set; 
    public string Day  get; set; 

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<DiscountDaysOfWeek> DiscountDaysOfWeeks  get; set; 

示例工作一:在下面的工作示例中,模型和实体具有相同的属性

Mapper.Register<DiscountPreventedPriceEnding, DiscountPreventedPriceEndingModel>();

var execPriceEndings = discs.SelectMany(x => x.DiscountPreventedPriceEndings)
                            .Map<IQueryable<DiscountPreventedPriceEnding>, IQueryable<DiscountPreventedPriceEndingModel>>();

任何帮助将不胜感激。

【问题讨论】:

这条线不能用 .Map, IQueryable>();如果您有可以映射 IQueryable 的示例,请给我看一个示例。你能把它改成ICollection吗? DiscountDaysOfWeekModel 有无参数构造函数吗?显示所涉及的类。 @SteveGreene 你好史蒂夫,我已经添加了类的代码 @BassamAlugili 我尝试使用 ICollection 但仍然有同样的错误。还添加了 IQuerable 工作的代码 【参考方案1】:

我很欣赏这是一个非常古老的问题,但鉴于我刚刚花了 4 个小时在 ExpressMapper 上调试类似的 There was an error: System.MissingMethodException: No parameterless constructor defined for this object 错误,我想我会加入我的发现。

所以我们遇到了和你类似的情况,因为我们有这样的领域模型(以下都是简化的例子):

public class Owner 

    public int? ID  get; set; 
    public string Name  get; set; 


public class Animal

    public int? ID  get; set; 
    public string Name  get; set; 
    public int? OwnerID  get; set; 
    [ForeignKey("OwnerID")]
    public Owner Owner  get; set; 

使用以下视图模型(即我们的 API 发送和接收的内容):

public class AnimalViewModel

    public int? ID  get; set; 
    public string Name  get; set; 
    public string Owner  get; set; 

使用这样的映射:

Mapper.Register<Animal, AnimalViewModel>();
Mapper.Register<AnimalViewModel, Animal>();

在映射到域模型和视图模型或从域模型和视图模型映射时,我们会得到MissingMethodException,尽管视图模型和域模型都有公共的默认构造函数。解决方案是手动映射域模型中的相关实体,并将它们从 ExpressMapper 的映射中排除,如下所示:

Mapper.Register<Animal, AnimalViewModel>()
    .Ignore(a => a.Owner);
Mapper.Register<AnimalViewModel, Animal>()
    .Ignore(a => a.Owner);

从阅读 EntityMapper 的源代码来看,MissingMethodException 似乎是一个完全与实际问题无关的红鲱鱼。实际问题似乎是它无法弄清楚如何将一种类型转换为另一种类型。在我们的例子中——复杂对象被映射到上面的基元/从基元映射——从映射器中排除相关对象并手动完成就足够了。

编辑:

经过进一步调查,我们将案例中的根本问题追溯到 EF 代理创建创建的生成类型(例如“MyModel_14289012”)与映射器中注册的类型不匹配这一事实。为防止这种情况,请将以下内容应用于您的上下文:

Context.Configuration.LazyLoadingEnabled = false;
Context.Configuration.ProxyCreationEnabled = false;

并手动包含模型中所需的任何嵌套/相关对象,如下所示:

Context.Animals
    .Include(a => a.Owner);

这会获取相关实体,但作为它们的实际类型而不是 EF 生成的类型。

【讨论】:

【参考方案2】:

Entity Framework 使用无参数构造函数来实例化类并使用反射来填充类属性。如果你有带参数的构造函数,那么默认的无参数构造函数是隐藏的,你必须将它添加到你的实体类中以供实体框架使用。

但是,如果我将链接实体映射到模型,则会出现错误

如果您的子实体缺少无参数构造函数并延迟加载,则 EF 在尝试实例化没有无参数构造函数的子实体时会失败。

注意:无参数构造函数不必是公共的。

【讨论】:

以上是关于ExpressMapper / EntityFramework - 没有为此对象定义无参数构造函数的主要内容,如果未能解决你的问题,请参考以下文章

为啥 ASP.Net Identity 不支持删除

EFCore-脚手架Scaffold发生Build Failed问题的终极解决

实战 EF(LINQ) 如何以子查询的形式来 Join

监视EntityFramework中的sql流转你需要知道的三种方式Log,SqlServerProfile, EFProfile