Adr*_* K. 11 c# generics asp.net-mvc abstract-class entity-framework
我已经尝试搜索SO以获得答案并偶然发现类似的问题,但我无法使用它们来解决我的问题,所以请尽量不要将其标记为重复.让我们继续谈谈真正的交易:
我有一个通用库,用于标准化实体框架数据库的第一个模型.这些是我创建的泛型类:
public abstract class GenericLookupModel : IActive, ICreated, IModified, IIdentity, IStringValue
{
public bool is_active { get; set; }
public string value { get; set; }
public string description { get; set; }
public DateTime created_on { get; set; }
public string created_by { get; set; }
public DateTime modified_on { get; set; }
public string modified_by { get; set; }
public int id {get;set;}
public void SetCreated(string creator = "SYSTEM")
{
created_by = creator;
created_on = DateTime.Now;
}
public void SetModified(string modifier = "SYSTEM")
{
modified_by = modifier;
modified_on = DateTime.Now;
}
}
Run Code Online (Sandbox Code Playgroud)
并且ViewModel的类具有预先设置的MVC属性
public abstract class GenericLookupViewModel
{
[Key]
public int ID { get; set; }
[Required]
[StringLength(300)]
public string Name { get; set; }
[StringLength(4000)]
public string Description { get; set; }
[Required]
public bool Active { get; set; }
[StringLength(50)]
[DisplayName("Record last modified by")]
public string ModifiedBy { get; set; }
[DisplayName("Record last modified Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime ModifiedOn { get; set; }
[StringLength(50)]
[DisplayName("Record created by")]
public string CreatedBy { get; set; }
[DisplayName("Record creation Date")]
[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime CreatedOn { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
另外,我已经创建了一个服务类,我打算在控制器中使用它来获取数据:
public abstract class GenericLookupModelDataService<TModel, TViewModel> : object
where TModel : GenericLookupModel, new()
where TViewModel : GenericLookupViewModel, new()
{
private readonly DbContext _db;
private DbContext entities
{
get { return _db; }
}
public GenericLookupModelDataService()
{
_db =
new DbContext(
System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnectionString"].ConnectionString);
}
public virtual IEnumerable<TViewModel> ReadAllActive()
{
return entities.Set<TModel>().Where(x => x.is_active).Select(product => new TViewModel
{
ID = product.id,
Active = product.is_active,
Description = product.description,
Name = product.value,
CreatedBy = product.created_by,
CreatedOn = product.created_on,
ModifiedBy = product.modified_by,
ModifiedOn = product.modified_on
});
}
public virtual IEnumerable<TViewModel> Read()
{
return entities.Set<TModel>().Select(product => new TViewModel
{
ID = product.id,
Active = product.is_active,
Description = product.description,
Name = product.value,
CreatedBy = product.created_by,
CreatedOn = product.created_on,
ModifiedBy = product.modified_by,
ModifiedOn = product.modified_on
});
}
public virtual void Create(TViewModel product, string username = "SYSTEM")
{
var entity = new TModel
{
is_active = product.Active,
description = product.Description,
value = product.Name,
};
entity.SetCreated();
entity.SetModified();
_db.Set<TModel>().Add(entity);
_db.SaveChanges();
}
public virtual void Update(TViewModel product, string username = "SYSTEM")
{
var entity = new TModel
{
id = product.ID,
is_active = product.Active,
description = product.Description,
value = product.Name
};
entity.SetModified();
_db.Set<TModel>().Attach(entity);
entities.Entry(entity).State = EntityState.Modified;
entities.SaveChanges();
}
public virtual void Destroy(TViewModel product)
{
var entity = new TModel {id = product.ID};
entities.Set<TModel>().Attach(entity);
entities.Set<TModel>().Remove(entity);
entities.SaveChanges();
}
public virtual TViewModel GetByID(int ID)
{
var item = entities.Set<TModel>().Find(ID);
var result = new TViewModel
{
ID = item.id,
Active = item.is_active,
CreatedBy = item.created_by,
CreatedOn = item.created_on,
Description = item.description,
ModifiedBy = item.modified_by,
ModifiedOn = item.modified_on,
Name = item.value
};
return result;
}
public void Dispose()
{
entities.Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
库编译得很好,我在我的MVC App里面的数据层项目中使用它.首先创建一个新的视图模型:
public class RoleViewModel : GenericLookupViewModel
{
}
Run Code Online (Sandbox Code Playgroud)
然后,让我们创建一个服务:
public class RoleService : GenericLookupModelDataService<tblkp_Role, RoleViewModel>
{
}
Run Code Online (Sandbox Code Playgroud)
使Entity Framework类继承自抽象模型:
partial class tblkp_Role : GenericLookupModel
{
}
Run Code Online (Sandbox Code Playgroud)
最后让我们创建我们的控制器:
public class EmployeeController : Controller
{
private RoleService roleService;
public EmployeeController()
{
dataService = new EmployeeService();
PopulateLookups();
}
private void PopulateLookups()
{
roleService = new RoleService();
ViewData["roles"] = roleService.ReadAllActive();
}
public ActionResult Index()
{
return View();
}
}
Run Code Online (Sandbox Code Playgroud)
对于代码墙感到抱歉,为简洁起见,已删除了一些代码.编译它时给了我3个错误:
更新:提供由EF自动生成的tblk_Role类(DB First方法):
using System;
using System.Collections.Generic;
public partial class tblkp_Role
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public tblkp_Role()
{
this.tbl_Employee = new HashSet<tbl_Employee>();
}
public int id { get; set; }
public string value { get; set; }
public string desciption { get; set; }
public bool is_active { get; set; }
public System.DateTime created_on { get; set; }
public string created_by { get; set; }
public System.DateTime modified_on { get; set; }
public string modified_by { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<tbl_Employee> tbl_Employee { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
更新2:纯文本格式的Erros:
错误33'DataLayer.Model.tblkp_Role'必须是具有公共无参数构造函数的非抽象类型,以便在泛型类型或方法'MyLib.Model.GenericLookupModelDataService <TModel,TViewModel>'c中将其用作参数'TModel' :\项目\来源\ MyLib中\ BIN \发布\中是指mylib.dll
错误32类型'DataLayer.Model.tblkp_Role'不能用作泛型类型或方法'MyLib.Model.GenericLookupModelDataService <TModel,TViewModel>'中的类型参数'TModel'.没有从'DataLayer.Model.tblkp_Role'到'MyLib.Model.GenericLookupModel'的装箱转换.C:\项目\来源\ MyLib中\ BIN \发布\中是指mylib.dll
Jep*_*sen 24
你有以下几点:
public abstract class GenericLookupModelDataService<TModel, TViewModel> : object
where TModel : GenericLookupModel, new()
where TViewModel : GenericLookupViewModel, new()
{
// ...
Run Code Online (Sandbox Code Playgroud)
该类有两个名为TModel
和的通用参数TViewModel
.其中每个都有对它的约束,在where
contextual关键字后面指出.
对于TModel
约束是:
GenericLookupModel
必须是所替换的类型的基类TModel
,并且new()
要求用于的类型TModel
必须公开一个public
接受零参数的实例构造函数.你问的一个错误是:
错误33"DataLayer.Model.tblkp_Role"必须是一个非抽象类型与公共参数构造,以便在通用类型或方法使用它作为参数"的TModel""MyLib.Model.GenericLookupModelDataService <TModel的,TViewModel>"
这只是意味着tblkp_Role
您尝试使用的类型TModel
不符合构造函数约束.你有0参数构造函数吗?
您询问的另一个错误是:
错误32类型'DataLayer.Model.tblkp_Role'不能用作泛型类型或方法'MyLib.Model.GenericLookupModelDataService <TModel,TViewModel>'中的类型参数'TModel'.没有从'DataLayer.Model.tblkp_Role'到'MyLib.Model.GenericLookupModel'的装箱转换.
这表示不满足基类约束.由于错误文本谈到"装箱转换",因此看起来tblkp_Role
编译器正在使用的类型实际上是值类型(struct
类型或enum
类型).类似的类型永远不能从GenericLookupModel
约束要求中派生出来.
它必须是tblkp_Role
C#编译器使用的类型,是与您定义的类型不同的另一种类型partial class tblkp_Role : GenericLookupModel
.您可能在引用的项目中有一些冲突的名称或一些重复的代码/名称.
在编译时错误的映像版本中,我们看到编译器还抱怨tblkp_Role
您使用的类型是在您没有引用的程序集中声明的.先尝试修复那个.一旦编译器可以看到所有细节,其他的将会消失,tblkp_Role
因为它具有对定义该类型的项目的引用.