Repository模式--采用EF Fluent API使用EntityTypeConfiguration分文件配置Model映射关系
EF中类EntityTypeConfiguration是一个很有用的类,在nopCommerence中就使用这个类来分文件分文件配置Model映射关系。今天我就来谈谈Repository模式在Entity Framework Code First中使用EntityTypeConfiguration的实现例子。
背景
为了简化我们就只使用两个表:分类表Category,产品类Product。最终项目结构如下:

注意:EfRepPatTest.Entity和EfRepPatTest.Data是类库项目,EfRepPatTest.Implementation是控制台项目。项目EfRepPatTest.Data需要对Entity Framework类库的引用。
BaseEntity.cs
创建一个所有实体的基类BaseEntity,把一些公共的属性封装在里面。
- public class BaseEntity<T>
- {
- public T Id { get; set; }
- }
这样表示所有实体都有一个字段为Id,类型为泛型这样可以满足所有类型的情况。
IRepository.cs:
下面定义一个泛型的接口IRepository,其中包括一个泛型的增、删、改。
- public interface IRepository<TEntity> where TEntity:class
- {
- IQueryable<TEntity> GetAll();
- TEntity GetById(object id);
- void Insert(TEntity entity);
- void Update(TEntity entity);
- void Delete(TEntity entity);
- }
Category.cs:
实体分类类
- public class Category:BaseEntity<int>
- {
- public virtual string Name { get; set; }
- public List<Product> Products { get; set; }
- }
Product.cs:
实体产品类
- public class Product:BaseEntity<long>
- {
- public virtual int CategoryId { get; set; }
- public virtual Category Category { get; set; }
- public virtual string Name { get; set; }
- public virtual int MinimumStockLevel { get; set; }
- }
IDbContext.cs:
接口IDbContext封装一些EF的公共接口方法。
- public interface IDbContext
- {
- IDbSet<TEntity> Set<TEntity>() where TEntity:class;
- int SaveChanges();
- void Dispose();
- }
DataContext.cs:
- public class DataContext: DbContext,IDbContext
- {
- public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
- {
- return base.Set<TEntity>();
- }
- }
CategoryMap.cs:
分类映射类继承于EntityTypeConfigureation<T>
- public class CategoryMap:EntityTypeConfiguration<Category>
- {
- public CategoryMap()
- {
- ToTable("Category");
- HasKey(c => c.Id).Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
- Property(c => c.Name).IsRequired().HasMaxLength(50);
- }
- }
ProductMap.cs:
产品类映射类继承于EntityTypeConfigureation<T>
- public class ProductMap:EntityTypeConfiguration<Product>
- {
- public ProductMap()
- {
- ToTable("Product");
- HasKey(p => p.Id).Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
- //CategoryId as foreign key
- HasRequired(p => p.Category)
- .WithMany(c=>c.Products)
- .HasForeignKey(p => p.CategoryId);
- Property(p => p.Name).IsRequired().HasMaxLength(100);
- Property(p => p.MinimumStockLevel);
- }
- }
在类DataContext中重写OnModelCreating方法依次加上我们新建的EF的Map配置文件,加入以下代码:
- modelBuilder.Configurations.Add(new CategoryMap());
- modelBuilder.Configurations.Add(new ProductMap());
- base.OnModelCreating(modelBuilder);
上面的代码可以优化一下,可以利用反射自动添加EF的Map配置文件,如下:
- public class DataContext: DbContext,IDbContext
- {
- public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
- {
- return base.Set<TEntity>();
- }
- protected override void OnModelCreating(DbModelBuilder modelBuilder)
- {
- var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
- .Where(type => !String.IsNullOrEmpty(type.Namespace))
- .Where(type => type.BaseType != null && type.BaseType.IsGenericType &&
- type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
- foreach (var type in typesToRegister)
- {
- dynamicconfigurationInstance = Activator.CreateInstance(type);
- modelBuilder.Configurations.Add(configurationInstance);
- }
- base.OnModelCreating(modelBuilder);
- }
- }
这样的好处是以后新加EF的实体Map类,不用修改DataContext。
RepositoryService.cs:
IRepositroy接口的一个具体实现的RepositoryService,数据访问采用EF的IDbContext。
- public class RepositoryService<TEntity>:IRepository<TEntity> where TEntity:class
- {
- private IDbContext Context;
- private IDbSet<TEntity> Entities
- {
- get { return this.Context.Set<TEntity>(); }
- }
- public RepositoryService(IDbContext context)
- {
- this.Context = context;
- }
- public IQueryable<TEntity> GetAll()
- {
- return Entities.AsQueryable();
- }
- public TEntity GetById(object id)
- {
- return Entities.Find(id);
- }
- public void Insert(TEntity entity)
- {
- Entities.Add(entity);
- }
- public void Update(TEntity entity)
- {
- if (entity == null)
- throw new ArgumentNullException("entity");
- this.Context.SaveChanges();
- }
- public void Delete(TEntity entity)
- {
- Entities.Remove(entity);
- }
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
- protected virtual void Dispose(bool disposing)
- {
- if (disposing)
- {
- if (this.Context != null)
- {
- this.Context.Dispose();
- this.Context = null;
- }
- }
- }
- }
新建一个类DataBaseInitializer为EF Code First数据库访问的初始化类。
- public class DataBaseInitializer : IDatabaseInitializer<DataContext>
- {
- public void InitializeDatabase(DataContext context)
- {
- context.Database.CreateIfNotExists();
- }
- }
新建一个控制台程序来测试上面的代码Program.cs:
- class Program
- {
- static void Main(string[] args)
- {
- var context = new DataContext();
- var dataBaseInitializer = new DataBaseInitializer();
- dataBaseInitializer.InitializeDatabase(context);
- var categoryRepository = new RepositoryService<Category>(context);
- //Adding category in the category entity
- var category = new Category()
- {
- Name = "Baverage"
- };
- var products = new List<Product>();
- //Adding product in the product entity
- var product = new Product()
- {
- Name = "Soft Drink A",
- MinimumStockLevel = 50
- };
- products.Add(product);
- product = new Product()
- {
- Name = "Soft Drink B",
- MinimumStockLevel = 30
- };
- products.Add(product);
- category.Products = products;
- //Insert category and save changes
- categoryRepository.Insert(category);
- context.SaveChanges();
- ///////////////////////////////////////////////////////////////////////////////
- /////////////////For the next project we shall add Dependency Injection////////
- ////////////////But now we have add a Service layer for test manually//////////
- ///////////////////////////////////////////////////////////////////////////////
- IProductService productRepository = new ProductService();
- Console.WriteLine("\n");
- Console.WriteLine("Product List:");
- Console.WriteLine("-------------------------------------------------");
- foreach (var product1 in productRepository.GetAll())
- {
- Console.WriteLine(string.Format("Product Name : {0}",product1.Name));
- if (product1.Id == 9)
- {
- product1.Name = "Soft Drink AAA";
- productRepository.Update(product1);
- }
- }
- Console.WriteLine("Press any key to exit");
- Console.ReadKey();
- }
- }
在配置文件添加数据库的链接。
App.config:
- <?xml version="1.0" encoding="utf-8"?>
- <configuration>
- <configSections>
- <!-- For more information
- on Entity Framework configuration, visit
- http://go.microsoft.com/fwlink/?LinkID=237468 -->
- <section name="entityFramework"
- type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection,
- EntityFramework, Version=4.4.0.0, Culture=neutral,
- PublicKeyToken=b77a5c561934e089"
- requirePermission="false" />
- </configSections>
- <entityFramework>
- <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory,
- EntityFramework" />
- </entityFramework>
- <connectionStrings>
- <add name="DataContext"
- providerName="System.Data.SqlClient"
- connectionString="Data
- Source=YourSERVER;Initial Catalog=EfDBExistRepository;Integrated
- Security=True;MultipleActiveResultSets=True;"/>
- </connectionStrings>
- </configuration>
注意:数据库链接结点名为“DataContext”,正好和我们自己写的类“DataContext”名字一样。这样EF框架就可以自动找到这个数据库链接信息。
参考:http://www.codeproject.com/Articles/561584/Repository-Pattern-with-Entity-Framework-using
Repository模式--采用EF Fluent API使用EntityTypeConfiguration分文件配置Model映射关系的更多相关文章
- Entity Framework 实体框架的形成之旅--Code First模式中使用 Fluent API 配置(6)
在前面的随笔<Entity Framework 实体框架的形成之旅--Code First的框架设计(5)>里介绍了基于Code First模式的实体框架的经验,这种方式自动处理出来的模式 ...
- EF Fluent API上
什么是Fluent API? 官方答案:EF 中内嵌的约定将 POCO 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体映射到约定指示外的其他对象,所以Fluent API和注解都是一种方 ...
- EF Fluent API
EntityTypeConfiguration 它可以为一个实体类,配置一个模型. Entity Framework 6 一次加载许多个 Fluent API 映射 如果对于许多实体有大量映射,则 O ...
- EF fluent API如何配置主键不自动增长
在Dbcontext中作如下添加: protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilde ...
- ef core中如何实现多对多的表映射关系
文档:https://docs.microsoft.com/en-us/ef/core/modeling/relationships class MyContext : DbContext { pub ...
- EF Core Fluent API
多对多配置 先安装 Install-Package MySql.Data.EntityFrameworkCore 创建3个表 创建类 public class Role { public long I ...
- 10.翻译系列:EF 6中的Fluent API配置【EF 6 Code-First系列】
原文链接:https://www.entityframeworktutorial.net/code-first/fluent-api-in-code-first.aspx EF 6 Code-Firs ...
- EntityFramework Code-First 简易教程(七)-------领域类配置之Fluent API
Fluent API配置: 前面我们已经了解到使用DataAnotations特性来覆写Code-First默认约定,现在我们来学习Fluent API. Fluent API是另一种配置领域类的方法 ...
- 使用 Fluent API 配置/映射属性和类型(摘自微软Data Access and Storage)
使用 Fluent API 配置/映射属性和类型 使用实体框架 Code First 时,默认行为是使用一组 EF 中内嵌的约定将 POCO 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体 ...
随机推荐
- FastDFS搭建单机图片服务器(二)
防丢失转载:https://blog.csdn.net/MissEel/article/details/80856194 根据 分布式文件系统 - FastDFS 在 CentOS 下配置安装部署 和 ...
- 你所遵循的PEP8代码规范是什么?请举例说明其要求?
1. 变量常量:大写加下划线 USER_CONSTANT.私有变量 : 小写和一个前导下划线 _private_value.Python 中不存在私有变量一说,若是遇到需要保护的变量,使用小写和一个前 ...
- EOJ Monthly 2019.2 A. 回收卫星
题目传送门 题意: 你可以询问一个三维坐标,机器会告诉你这个坐标在不在目标圆中, 并且(0,0,0)是一定在圆上的,叫你求出圆心坐标 思路: 因为(0,0,0)一定在圆上,所以我们可以把圆心分成3个坐 ...
- HTML5-video(播放暂停视频;打开关闭声音;进度条)
<!DOCTYPE html> <html> <head> <title>HTML5-video(播放暂停视频:打开关闭声音:进度条)</titl ...
- Web学习之JS总结
银角大王武Sir的博客地址 银角大王武Sir的博客地址二 1.Javascript的作用域链 由于javascript没有块级作用域,而且每个函数作为一个作用域,如果出现嵌套函数,则就会出现作用域链 ...
- Linux手册页内容
总用9页 man1:可执行程序或shell命令 man2:系统调用(kernel提供的函数) man3:库调用(程序库中的函数) man4:/dev中的特殊文件 ...
- BZOJ1135 LYZ(POI2009) Hall定理+线段树
做这个题之前首先要了解判定二分图有没有完备匹配的Hall定理: 那么根据Hell定理,如果任何一个X子集都能连大于等于|S|的Y子集就可以获得完备匹配,那么就是: 题目变成只要不满足上面这个条件就能得 ...
- thinkphp model
模型样板 <?php namespace app\model; use think\Db; use think\Model; class Admin extends Model { //表名 p ...
- 机器学习:2.NPL自然语言处理
1. 词带的简单解释: 每一个词出现了多少次,缺点是不知道顺序 2.seq2seq自然语言处理的核心 RNN: 一对一:输入一个,输出一个 一对多:输入一个,输出多个 多对一:输入多个,输出一个 多对 ...
- 20.Nodejs基础知识(上)——2019年12月16日
2019年12月16日18:58:55 2019年10月04日12:20:59 1. nodejs简介 Node.js是一个让JavaScript运行在服务器端的开发平台,它让JavaScript的触 ...