无法将类型'System.Collections.Generic.List <model#1>'隐式转换为'System.Collections.Generic.List <model#2>

时间:2016-06-26 09:14:32

标签: c# asp.net-mvc entity-framework

我正在使用MVC5和EF6。我得到以下转换错误

  

无法隐式转换类型   System.Collections.Generic.List<TreaceabilitySystem.GLB_M_PROFITCENTER>   至   System.Collections.Generic.List<TreaceabilitySystem.Models.Profitcenter>

        private TSEntities db = new TSEntities();
        // GET: Profitcenter
        public ActionResult Index()
        {

            List<Profitcenter> profitcenter = new List<Profitcenter>();
            profitcenter = db.GLB_M_PROFITCENTER.ToList(); //Error coming up here
            return View(profitcenter.ToList());
        }

我的模特在这里: 当我在.edmx

中添加表格时,通过EF创建此模型
 public partial class GLB_M_PROFITCENTER
        {
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
            public GLB_M_PROFITCENTER()
            {
                this.GLB_M_USERMASTER = new HashSet<GLB_M_USERMASTER>();
            }

            public string PROFITCENTER_CODE { get; set; }
            public string PROFITCENTER_NAME { get; set; }
            public string DESCRIPTION { get; set; }
            public bool ISACTIVE { get; set; }
            public int CREATEDBY { get; set; }
            public System.DateTime CREATED_DATE { get; set; }
            public Nullable<int> UPDATEDBY { get; set; }
            public Nullable<System.DateTime> UPDATED_DATETIME { get; set; }

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

我创建了以下模型来更改显示名称和验证目的

 [MetadataType(typeof(Profitcenter))]
    public partial class GLB_M_PROFITCENTER { }

     public class Profitcenter
        {
            [Required(ErrorMessage = "*")]
            [DisplayName("Profitcenter Code")]
            public string PROFITCENTER_CODE { get; set; }
            [Required(ErrorMessage = "*")]
            [DisplayName("Profitcenter Name")]
            public string PROFITCENTER_NAME { get; set; }


            [DisplayName("Description")]
            public string DESCRIPTION { get; set; }

            [DisplayName("Is Active")]
            public bool ISACTIVE { get; set; }

            [DisplayName("Created By")]
            public int CREATEDBY { get; set; }

            [DisplayName("Created Timestamp")]
            public System.DateTime CREATED_DATE { get; set; }

            [DisplayName("Upated by")]
            public Nullable<int> UPDATEDBY { get; set; }

            [DisplayName("Updated Timestamp")]
            public DateTime UPDATED_DATETIME
            {
                get; set;
            }
        }

两个型号完全相同,我错过了什么吗? 我该如何解决这个问题?

4 个答案:

答案 0 :(得分:5)

  

两个模型完全相同

这并不意味着您可以将一个分配给另一个。要使此代码有效:

Bar

Foo必须是Bar的基本类型。在这种情况下并非如此,Foopublic Profitcenter Map(GLB_M_PROFITCENTER input) { return new Profitcenter { PROFITCENTER_CODE = input.PROFITCENTER_CODE, ... }; } 碰巧具有相同的属性名称。

您需要从一个映射到另一个:

Select()

您可以使用List<Profitcenter> profitcenter = new List<Profitcenter>(); profitcenter = db.GLB_M_PROFITCENTER.Select(Map).ToList();

进行整个列表的映射
GLB_M_PROFITCENTER

自动执行此操作的方法可能是使用AutoMapper,如果双方的所有属性都以相同的名称命名,则该方法尤其有效。

这只能部分回答你的问题。您有两种类型:Profitcenter,一个表示数据库表的Entity Framework生成的类,以及MetadataType,其中添加了可用于使用MetadataType属性进行输入验证的属性

我不是后者的粉丝,因为您之后使用Entity Framework模型作为UI图层的视图模型。你不应该,你可以从部分类定义中删除List<GLB_M_PROFITCENTER> profitcenter = db.GLB_M_PROFITCENTER.ToList(); return View(profitcenter); 属性。

所以你可以使用MetadataType,但从不真正实例化那个类型(毕竟,它是元数据类型):

@model IEnumerable<GLB_M_PROFITCENTER>

并制作您的观点MetadataType。然后MVC将读取GLB_M_PROFITCENTER的{​​{1}}属性,并应用DisplayName应用的元数据(Profitcenter,...)(但您不应该)

或者您可以简单地应用映射,从而将您的视图模型与实体模型(以及您的数据库)分离,并带来所有额外的好处。

答案 1 :(得分:1)

某些编程语言, C#和其他类C语言不同,允许使用所谓的"duck typing",如果它们都是&#34; quack,它们可以让您分配不同的类型同样的方式&#34;。

但是,在C#中,只能将类的实例分配给相同类型的变量,或基类型(类扩展的类或它实现的接口)。即使你有两个看起来完全相同的课程,你也无法从其中一个课程分配到另一个课程。版本4.0之前的.NET甚至不支持正确的通用covariance and contravariance,这意味着即使IEnumerable<Tderived>IEnumerable<Tbase>,您也无法将Tderived分配给Tbase源自AutoMapper

解决方案可能是:

  1. 使用映射从一个类到另一个类的工具(即在同名的属性之间复制),如stringAttributes

  2. 重新设计你的应用程序以拥有一个单独的程序集,其中包含要在其他程序集类型之间共享的公共实体(也不是一个坏主意),或者

  3. 提取接口,以便您可以分配到此基本接口。

  4. 使用映射来解决此问题的情况并不少见,因为您经常希望使用普通data transfer objects来在层之间移动数据,因此使用自动化工具可以,但是如果您可以保留所有实体在由DAL和业务层引用的单独程序集中,但对它们一无所知,那么它是一种更好的方法,因为它避免了任何运行时映射问题。

答案 2 :(得分:0)

如果成员名称相同 - 使用自动映射器 - 它将自动转换每种类型。

SELECT
    users 
FROM
    yourTable
WHERE
    Createddate >= cast(floor(cast(dateadd(day,-1,getdate())as float))as datetime)
AND
    Createddate < cast(ceiling(cast(dateadd(day,-1,getdate())as float))as datetime)

然后你可以打电话

Mapper.CreateMap<SourceType, DestinationType>()

答案 3 :(得分:0)

GLB_M_PROFITCENTER和Profitcenter的类型不同,您只需共享元数据,以便从viewmodel到实体模型共享属性。您应该使用linq投影将一种类型转换为其他类型

db.GLB_M_PROFITCENTER.select(e => new Profitcenter() {
     /* props mapping*/
}).ToList()

您也可以使用映射引擎,例如AutoMapper

相关问题