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 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体 ...
随机推荐
- BZOJ 1875(DP+矩阵快速幂)
题面 传送门 分析 容易想到根据点来dp,设dp[i][j]表示到i点路径长度为j的方案数 状态转移方程为dp[i][k]=∑(i,j)∈Edp[j][k−1]" role="pr ...
- swiper和tab相结合
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- Elasticsearch7.X 入门学习第三课笔记----search api学习(URI Search)
原文:Elasticsearch7.X 入门学习第三课笔记----search api学习(URI Search) 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出 ...
- 安装paramiko的方法
打开cmd命令行 输入 cd /d C:\Python27\Scripts 输入 pip install paramiko pip install pika -i https://pypi.doub ...
- PayPal支付对接
开发时间:2019-04-30 我的目标:在我们公司的海外网站上,接入PayPal支付,美国用户在线完成付款. 准备: (1)准备:公司注册信息(执照,注册号,法人等),法人信息(身份证,住址等) ( ...
- 12JDBC
1.JDBC概述 JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java ...
- mysql +keeplive+drbd高可用架构(MHA基于监听端口VIP的高可用)
1MySQL+DRBD+keepalived高可用架构 DRBD(DistributedReplicatedBlockDevice)是一个基于块设备级别在远程服务器直接同步和镜像数据的开源软件,类似于 ...
- ARM Linux BenchMark
http://tonyho.github.io/ARM%20Linux%20BenchMark.html 1.背景说明 许多公司有很多不同的ARM SoC的研发产品,ARM核心可能有Cortex-A8 ...
- 基于 Ansible 的 ELK 部署说明
ELK-Ansible使用手册 ELK-Ansible 是基于 Ansible 的 Playbooks 研发的 ELK集群部署工具.本文将介绍如何使用 ELK-Ansible 快速部署 ELK 集群. ...
- 21.Nodejs基础知识(下)——2019年12月16日
2019年10月04日16:56:23 7. 模块 7.1 暴露一个类,字段 var bar = require("./bar.js"); var msg = "你好&q ...