现有多项目架构引入POCO类的技术疑问及示例需求
嘿,结合你现在的项目结构和要引入POCO的需求,我来逐个解答你的疑问,再给你一个简单的落地示例:
疑问解答
1. 是否需要新建类库来存放这些POCO类?
必须要!单独的POCO类库是最佳实践——因为你接下来要新增手机、桌面等多个应用,这个类库可以被所有需要使用实体的项目直接引用,避免每个项目重复定义实体,同时保证所有地方用的是同一个实体模型,不会出现不一致的问题。建议命名成Domain.Models或者Core.Entities,清晰易懂。
2. 若新建类库,如何生成POCO类?尤其BusinessLogic层存在List<Customer> GetCustomers()这类方法时该如何处理?
生成POCO的方式分场景选择:
- Database First场景(你当前用EDMX/DBML):用T4模板自动生成最省心。比如EF的EDMX,右键模型→添加代码生成项→选择「EF POCO实体生成器」,它会自动根据数据库表生成干净的POCO类,还会生成对应的POCO版本上下文;Linq to SQL也有第三方T4模板,或者用
SqlMetal命令行工具生成POCO。 - 小项目/自定义需求:也可以手动写,但大项目强烈建议用工具节省时间。
至于List<Customer> GetCustomers()这类方法,核心是把原来返回的EF/L2S自动生成的实体,替换成POCO类:
- 在DAL层,查询出EF/L2S实体后,通过映射工具(比如AutoMapper)或者手动映射,转换成POCO类;
- BusinessLogic层的方法返回POCO的
List<Customer>,这样上层应用(Web、手机、桌面)完全不用依赖EF/L2S,只需要引用POCO类库和BusinessLogic即可。
3. 是否必须手动生成每个属性并复制数据库表中的列?
完全不用!有很多工具可以帮你自动生成:
- EF的EDMX自带POCO生成模板,一键生成所有实体的属性;
- Linq to SQL可以用
SqlMetal命令行工具生成POCO; - VS自带「粘贴特殊」功能:如果能拿到表结构的JSON(比如从数据库导出或API返回),右键→粘贴特殊→将JSON粘贴为类;
- 大项目还可以用CodeSmith这类代码生成工具,或者自己写个小脚本从数据库系统表读取元数据生成POCO。
4. 我的DAL层中有用于扩展列方法的分部类(如NormaliseCustomerName),是否需要将这些方法迁移到POCO类中?
看这些方法的用途来决定:
- 如果是和实体本身业务逻辑相关的(比如
NormaliseCustomerName是处理Customer的Name属性),建议迁移到POCO类里:要么写成实例方法(比如customer.NormaliseName()),要么写成针对POCO的扩展方法。这样所有使用POCO的地方都能直接调用,更符合面向对象设计。 - 如果这些方法依赖EF/L2S特定特性(比如依赖EF的跟踪属性、延迟加载),那就要先调整逻辑,去掉对EF/L2S的依赖后再迁移。
举个例子,原来的c.Name = myValue.Name.NormaliseCustomerName();可以改成通用的字符串扩展方法,或者POCO的实例方法,这样通用性更强。
简单落地示例
1. 新建POCO类库:Domain.Models
// Domain.Models/Customer.cs namespace Domain.Models { public class Customer { public int Id { get; set; } public string Name { get; set; } public string Email { get; set; } public DateTime CreatedDate { get; set; } // 迁移原来的Normalise逻辑为实例方法 public void NormaliseName() { if (!string.IsNullOrEmpty(Name)) { Name = Name.Trim().ToUpperInvariant(); } } } // 或者写成通用扩展方法(更灵活) public static class CustomerExtensions { public static string NormaliseCustomerName(this string name) { return name?.Trim().ToUpperInvariant(); } } }
2. 调整DAL层(引用Domain.Models和AutoMapper)
// DAL/CustomerRepository.cs using Domain.Models; using AutoMapper; using YourEDMXNamespace; // 替换成你原来的EF实体命名空间 public class CustomerRepository { private readonly YourEDMXEntities _context; private readonly IMapper _mapper; public CustomerRepository() { _context = new YourEDMXEntities(); // 配置EF实体到POCO的映射 var config = new MapperConfiguration(cfg => { cfg.CreateMap<YourEDMXNamespace.Customer, Domain.Models.Customer>(); cfg.CreateMap<Domain.Models.Customer, YourEDMXNamespace.Customer>(); }); _mapper = config.CreateMapper(); } public List<Domain.Models.Customer> GetCustomers() { var efCustomers = _context.Customers.ToList(); // 映射为POCO类返回 return _mapper.Map<List<Domain.Models.Customer>>(efCustomers); } public void AddCustomer(Domain.Models.Customer customer) { // 先标准化名字 customer.NormaliseName(); // 映射回EF实体 var efCustomer = _mapper.Map<YourEDMXNamespace.Customer>(customer); _context.Customers.Add(efCustomer); _context.SaveChanges(); } }
3. 调整BusinessLogic层(引用Domain.Models和DAL)
// BusinessLogic/ICustomer.cs using Domain.Models; public interface ICustomer { List<Customer> GetCustomers(); void AddCustomer(Customer customer); // 其他方法:Update、Delete等 } // BusinessLogic/CustomerService.cs using Domain.Models; using DAL; public class CustomerService : ICustomer { private readonly CustomerRepository _repo; public CustomerService() { _repo = new CustomerRepository(); } public List<Customer> GetCustomers() { return _repo.GetCustomers(); } public void AddCustomer(Customer customer) { _repo.AddCustomer(customer); } }
4. Website项目使用(引用BusinessLogic和Domain.Models)
// Website/Default.aspx.cs using BusinessLogic; using Domain.Models; protected void Page_Load(object sender, EventArgs e) { ICustomer customerService = new CustomerService(); var customers = customerService.GetCustomers(); // 绑定到GridView展示 GridView1.DataSource = customers; GridView1.DataBind(); }
之后新增的手机/桌面应用,只需要引用Domain.Models和BusinessLogic,就能直接复用所有业务逻辑,完全不用关心DAL层的EF/L2S实现细节。
内容的提问来源于stack exchange,提问作者Computer
相关产品推荐
相关产品推荐

