我正在使用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;
}
}
两个型号完全相同,我错过了什么吗? 我该如何解决这个问题?
答案 0 :(得分:5)
两个模型完全相同
这并不意味着您可以将一个分配给另一个。要使此代码有效:
Bar
Foo
必须是Bar
的基本类型。在这种情况下并非如此,Foo
和public 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
。
解决方案可能是:
使用映射从一个类到另一个类的工具(即在同名的属性之间复制),如stringAttributes
或
重新设计你的应用程序以拥有一个单独的程序集,其中包含要在其他程序集类型之间共享的公共实体(也不是一个坏主意),或者
提取接口,以便您可以分配到此基本接口。
使用映射来解决此问题的情况并不少见,因为您经常希望使用普通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