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

时间:2016-06-23 15:38:30

标签: c# .net entity-framework object-object-mapping

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

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

但如果我将链接的实体映射到模型,那么我收到错误

  

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

数据库结构:

enter image description here

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

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:3)

我很欣赏这是一个非常古老的问题,但考虑到我只花了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生成的类型。

答案 1 :(得分:0)

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

  

但如果我将链接的实体映射到模型,那么我收到错误

如果你的子实体缺少无参数构造函数并且延迟加载,那么当它试图实例化没有无参数构造函数的子实体时,EF就会失败。

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