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 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体 ...
随机推荐
- [19/05/06-星期一] JDBC(Java DataBase Connectivity,java数据库连接)_基本知识
一.概念 JDBC(Java Database Connectivity)为java开发者使用数据库提供了统一的编程接口,它由一组java类和接口组成.是java程序与数据库系统通信的标准API. J ...
- java项目中,针对缓存问题的处理方式【接口中的处理方式】
1.在service包中,分别建立了关于缓存的一系列的接口.类等,封装到一个工具包中: 临时缓存的接口(代码部分): package com.tools; import java.util.Date; ...
- 剑指Offer编程题(Java实现)——二维数组中的查找
题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...
- poj-2516.minimum cost(k次费用流)
Minimum Cost Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 19883 Accepted: 7055 Des ...
- 全球编程语言薪资排行榜,Java竟然垫底!!!
近日,Stack Overflow 发布了 2019 年度开发者调查报告,这次调查有来自全球的几乎将近 90000 名开发者参与,是对世界各地开发人员进行的规模最大,最全面的调查. 这次调查报告中总结 ...
- 循环结构 :do-while
循环结构 :do-while 循环四要素: 1.初始化条件 2.循环条件 3.循环体 4.迭代条件 格式: 1.初始化条件 do{ 3.循环体 4.迭代条件 }while(2.循环条件); publi ...
- [2019杭电多校第一场][hdu6583]Typewriter(后缀自动机&&dp)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6583 大致题意是说可以花费p在字符串后添加一个任意字符,或者花费q在字符串后添加一个当前字符串的子串. ...
- HDU 5945 题解(DP)(单调队列)
题面: Fxx and game Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) T ...
- uWSGI、uwsgi、WSGI、之间的关系,为什么要用nginx加uWSGI部署。
WSGI 协议 WSGI:是一种协议规范,起到规范参数的作用,就像告诉公路一样,规定超车靠右行,速度不低于90km/h,等.但这一切都是对双方进行沟通,比如,重庆到武汉这条高速路,这儿重庆和武汉就各为 ...
- Linux性能优化从入门到实战:16 文件系统篇:总结磁盘I/O指标/工具、问题定位和调优
(1)磁盘 I/O 性能指标 文件系统和磁盘 I/O 指标对应的工具 文件系统和磁盘 I/O 工具对应的指标 (2)磁盘 I/O 问题定位分析思路 (3)I/O 性能优化思路 Step 1:首先采用 ...