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 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体 ...
随机推荐
- Notepad++-第一篇命令行语句执行之编译、运行Java
1.让Notepad++编译和运行Java,在电脑上要已经配置好了Java的开发环境 2.在Notepad++上面的选项栏中找到 Plugins--->Plugin Admin 3.在Avail ...
- 剑指Offer编程题(Java实现)——二维数组中的查找
题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...
- ajax与json总结
1.jquery中调用ajax方法 $.ajax({ async:true, type:"post", url:"xxxServlet", data:{&quo ...
- Monitor HDU6514 二维差分入门学习
Monitor HDU 6514 二维差分入门学习 题意 小腾有\(n*m\)的田地,但是有小偷来偷东西,在一片矩形区域上,有一部分区域是监控可以覆盖到的,这部分区域由一个或多个包含于该矩形区域的小矩 ...
- [常用类]时间内Date、SimpleDateFormat、Calendar类
Date类的概述是util包下的,不能导入sql包的.* 类 Date 表示特定的瞬间,精确到毫秒. *构造方法 * public Date() * public Date(long date) 如果 ...
- Linux快速访问多个目录
Linux下实现多个目录之间快速切换 dirs -v # 显示栈目录dirs -c # 清空栈目录 pushd # 加入当前目录pushd director # 加入指定目录pushd +/-i ...
- R语言基础篇——数据对象
1.基本数据类型(numeric,logical,character,NA,double,complex,integer) 2.日期变量 常用函数 Sys.Date()-返回系统当前的日期,Sys.t ...
- Angular.js 使用获取验证码按钮实现-倒计时
获取验证码界面效果如图: 需要实现以下逻辑 按钮不可选 --输入电话号码,按钮可选 --点击获取,进入倒计时,按钮不可选 --倒计时结束,回到初识状态 核心代码: var cd = 60; var t ...
- CentOS7系统局域网内配置本地yum源解决cannot find a valid baseurl for repo
一. 问题详情 因为服务器无法连接外网,所有直接用yum安装某些功能将受到影响,报错如下: Error: Cannot find a valid baseurl for repo: base ...
- Linux基础之输入输出
第十五章 输入输出 一.重定向概述 1.1.什么是重定向? 将原本要输出到屏幕的数据信息,重新定向到指定的文件中. 比如:每天凌晨定时备份数据,希望将备份数据的结果保存到某个文件中.这样第二天通过查看 ...