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,把一些公共的属性封装在里面。

  1. public class BaseEntity<T>
  2. {
  3. public T Id { get; set; }
  4. }

这样表示所有实体都有一个字段为Id,类型为泛型这样可以满足所有类型的情况。

IRepository.cs:

下面定义一个泛型的接口IRepository,其中包括一个泛型的增、删、改。

  1. public interface IRepository<TEntity> where TEntity:class
  2. {
  3. IQueryable<TEntity> GetAll();
  4. TEntity GetById(object id);
  5. void Insert(TEntity entity);
  6. void Update(TEntity entity);
  7. void Delete(TEntity entity);
  8. }

Category.cs:

实体分类类

  1. public class Category:BaseEntity<int>
  2. {
  3. public virtual string Name { get; set; }
  4. public List<Product> Products { get; set; }
  5. }

Product.cs:

实体产品类

  1. public class Product:BaseEntity<long>
  2. {
  3. public virtual int CategoryId { get; set; }
  4. public virtual Category Category { get; set; }
  5. public virtual string Name { get; set; }
  6. public virtual int MinimumStockLevel { get; set; }
  7. }

IDbContext.cs:

接口IDbContext封装一些EF的公共接口方法。

  1. public interface IDbContext
  2. {
  3. IDbSet<TEntity> Set<TEntity>() where TEntity:class;
  4. int SaveChanges();
  5. void Dispose();
  6. }

DataContext.cs:

  1. public class DataContext: DbContext,IDbContext
  2. {
  3. public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
  4. {
  5. return base.Set<TEntity>();
  6. }
  7. }

CategoryMap.cs:

分类映射类继承于EntityTypeConfigureation<T>

  1. public class CategoryMap:EntityTypeConfiguration<Category>
  2. {
  3. public CategoryMap()
  4. {
  5. ToTable("Category");
  6. HasKey(c => c.Id).Property(c => c.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
  7. Property(c => c.Name).IsRequired().HasMaxLength(50);
  8. }
  9. }

ProductMap.cs:

产品类映射类继承于EntityTypeConfigureation<T>

  1. public class ProductMap:EntityTypeConfiguration<Product>
  2. {
  3. public ProductMap()
  4. {
  5. ToTable("Product");
  6. HasKey(p => p.Id).Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
  7. //CategoryId as foreign key
  8. HasRequired(p => p.Category)
  9. .WithMany(c=>c.Products)
  10. .HasForeignKey(p => p.CategoryId);
  11. Property(p => p.Name).IsRequired().HasMaxLength(100);
  12. Property(p => p.MinimumStockLevel);
  13. }
  14. }

在类DataContext中重写OnModelCreating方法依次加上我们新建的EF的Map配置文件,加入以下代码:

  1. modelBuilder.Configurations.Add(new CategoryMap());
  2. modelBuilder.Configurations.Add(new ProductMap());
  3. base.OnModelCreating(modelBuilder);

上面的代码可以优化一下,可以利用反射自动添加EF的Map配置文件,如下:

  1. public class DataContext: DbContext,IDbContext
  2. {
  3. public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
  4. {
  5. return base.Set<TEntity>();
  6. }
  7. protected override void OnModelCreating(DbModelBuilder modelBuilder)
  8. {
  9. var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()
  10. .Where(type => !String.IsNullOrEmpty(type.Namespace))
  11. .Where(type => type.BaseType != null && type.BaseType.IsGenericType &&
  12. type.BaseType.GetGenericTypeDefinition() == typeof(EntityTypeConfiguration<>));
  13. foreach (var type in typesToRegister)
  14. {
  15. dynamicconfigurationInstance = Activator.CreateInstance(type);
  16. modelBuilder.Configurations.Add(configurationInstance);
  17. }
  18. base.OnModelCreating(modelBuilder);
  19. }
  20. }

这样的好处是以后新加EF的实体Map类,不用修改DataContext。

RepositoryService.cs:

IRepositroy接口的一个具体实现的RepositoryService,数据访问采用EF的IDbContext。

  1. public class RepositoryService<TEntity>:IRepository<TEntity> where TEntity:class
  2. {
  3. private IDbContext Context;
  4. private IDbSet<TEntity> Entities
  5. {
  6. get { return this.Context.Set<TEntity>(); }
  7. }
  8. public RepositoryService(IDbContext context)
  9. {
  10. this.Context = context;
  11. }
  12. public IQueryable<TEntity> GetAll()
  13. {
  14. return Entities.AsQueryable();
  15. }
  16. public TEntity GetById(object id)
  17. {
  18. return Entities.Find(id);
  19. }
  20. public void Insert(TEntity entity)
  21. {
  22. Entities.Add(entity);
  23. }
  24. public void Update(TEntity entity)
  25. {
  26. if (entity == null)
  27. throw new ArgumentNullException("entity");
  28. this.Context.SaveChanges();
  29. }
  30. public void Delete(TEntity entity)
  31. {
  32. Entities.Remove(entity);
  33. }
  34. public void Dispose()
  35. {
  36. Dispose(true);
  37. GC.SuppressFinalize(this);
  38. }
  39. protected virtual void Dispose(bool disposing)
  40. {
  41. if (disposing)
  42. {
  43. if (this.Context != null)
  44. {
  45. this.Context.Dispose();
  46. this.Context = null;
  47. }
  48. }
  49. }
  50. }

新建一个类DataBaseInitializer为EF Code First数据库访问的初始化类。

  1. public class DataBaseInitializer : IDatabaseInitializer<DataContext>
  2. {
  3. public void InitializeDatabase(DataContext context)
  4. {
  5. context.Database.CreateIfNotExists();
  6. }
  7. }

新建一个控制台程序来测试上面的代码Program.cs:

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. var context = new DataContext();
  6. var dataBaseInitializer = new DataBaseInitializer();
  7. dataBaseInitializer.InitializeDatabase(context);
  8. var categoryRepository = new RepositoryService<Category>(context);
  9. //Adding category in the category entity
  10. var category = new Category()
  11. {
  12. Name = "Baverage"
  13. };
  14. var products = new List<Product>();
  15. //Adding product in the product entity
  16. var product = new Product()
  17. {
  18. Name = "Soft Drink A",
  19. MinimumStockLevel = 50
  20. };
  21. products.Add(product);
  22. product = new Product()
  23. {
  24. Name = "Soft Drink B",
  25. MinimumStockLevel = 30
  26. };
  27. products.Add(product);
  28. category.Products = products;
  29. //Insert category and save changes
  30. categoryRepository.Insert(category);
  31. context.SaveChanges();
  32. ///////////////////////////////////////////////////////////////////////////////
  33. /////////////////For the next project we shall add Dependency Injection////////
  34. ////////////////But now we have add a Service layer for test manually//////////
  35. ///////////////////////////////////////////////////////////////////////////////
  36. IProductService productRepository = new ProductService();
  37. Console.WriteLine("\n");
  38. Console.WriteLine("Product List:");
  39. Console.WriteLine("-------------------------------------------------");
  40. foreach (var product1 in productRepository.GetAll())
  41. {
  42. Console.WriteLine(string.Format("Product Name : {0}",product1.Name));
  43. if (product1.Id == 9)
  44. {
  45. product1.Name = "Soft Drink AAA";
  46. productRepository.Update(product1);
  47. }
  48. }
  49. Console.WriteLine("Press any key to exit");
  50. Console.ReadKey();
  51. }
  52. }

在配置文件添加数据库的链接。

App.config:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <configuration>
  3. <configSections>
  4. <!-- For more information
  5. on Entity Framework configuration, visit
  6. http://go.microsoft.com/fwlink/?LinkID=237468 -->
  7. <section name="entityFramework"
  8. type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection,
  9. EntityFramework, Version=4.4.0.0, Culture=neutral,
  10. PublicKeyToken=b77a5c561934e089"
  11. requirePermission="false" />
  12. </configSections>
  13. <entityFramework>
  14. <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory,
  15. EntityFramework" />
  16. </entityFramework>
  17. <connectionStrings>
  18. <add name="DataContext"
  19. providerName="System.Data.SqlClient"
  20. connectionString="Data
  21. Source=YourSERVER;Initial Catalog=EfDBExistRepository;Integrated
  22. Security=True;MultipleActiveResultSets=True;"/>
  23. </connectionStrings>
  24. </configuration>

注意:数据库链接结点名为“DataContext”,正好和我们自己写的类“DataContext”名字一样。这样EF框架就可以自动找到这个数据库链接信息。

参考:http://www.codeproject.com/Articles/561584/Repository-Pattern-with-Entity-Framework-using

Repository模式--采用EF Fluent API使用EntityTypeConfiguration分文件配置Model映射关系的更多相关文章

  1. Entity Framework 实体框架的形成之旅--Code First模式中使用 Fluent API 配置(6)

    在前面的随笔<Entity Framework 实体框架的形成之旅--Code First的框架设计(5)>里介绍了基于Code First模式的实体框架的经验,这种方式自动处理出来的模式 ...

  2. EF Fluent API上

     什么是Fluent API? 官方答案:EF 中内嵌的约定将 POCO 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体映射到约定指示外的其他对象,所以Fluent API和注解都是一种方 ...

  3. EF Fluent API

    EntityTypeConfiguration 它可以为一个实体类,配置一个模型. Entity Framework 6 一次加载许多个 Fluent API 映射 如果对于许多实体有大量映射,则 O ...

  4. EF fluent API如何配置主键不自动增长

    在Dbcontext中作如下添加: protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilde ...

  5. ef core中如何实现多对多的表映射关系

    文档:https://docs.microsoft.com/en-us/ef/core/modeling/relationships class MyContext : DbContext { pub ...

  6. EF Core Fluent API

    多对多配置 先安装 Install-Package MySql.Data.EntityFrameworkCore 创建3个表 创建类 public class Role { public long I ...

  7. 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 ...

  8. EntityFramework Code-First 简易教程(七)-------领域类配置之Fluent API

    Fluent API配置: 前面我们已经了解到使用DataAnotations特性来覆写Code-First默认约定,现在我们来学习Fluent API. Fluent API是另一种配置领域类的方法 ...

  9. 使用 Fluent API 配置/映射属性和类型(摘自微软Data Access and Storage)

    使用 Fluent API 配置/映射属性和类型 使用实体框架 Code First 时,默认行为是使用一组 EF 中内嵌的约定将 POCO 类映射到表.但是,有时您无法或不想遵守这些约定,需要将实体 ...

随机推荐

  1. [19/05/06-星期一] JDBC(Java DataBase Connectivity,java数据库连接)_基本知识

    一.概念 JDBC(Java Database Connectivity)为java开发者使用数据库提供了统一的编程接口,它由一组java类和接口组成.是java程序与数据库系统通信的标准API. J ...

  2. java项目中,针对缓存问题的处理方式【接口中的处理方式】

    1.在service包中,分别建立了关于缓存的一系列的接口.类等,封装到一个工具包中: 临时缓存的接口(代码部分): package com.tools; import java.util.Date; ...

  3. 剑指Offer编程题(Java实现)——二维数组中的查找

    题目描述 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数 ...

  4. poj-2516.minimum cost(k次费用流)

    Minimum Cost Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 19883   Accepted: 7055 Des ...

  5. 全球编程语言薪资排行榜,Java竟然垫底!!!

    近日,Stack Overflow 发布了 2019 年度开发者调查报告,这次调查有来自全球的几乎将近 90000 名开发者参与,是对世界各地开发人员进行的规模最大,最全面的调查. 这次调查报告中总结 ...

  6. 循环结构 :do-while

    循环结构 :do-while 循环四要素: 1.初始化条件 2.循环条件 3.循环体 4.迭代条件 格式: 1.初始化条件 do{ 3.循环体 4.迭代条件 }while(2.循环条件); publi ...

  7. [2019杭电多校第一场][hdu6583]Typewriter(后缀自动机&&dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6583 大致题意是说可以花费p在字符串后添加一个任意字符,或者花费q在字符串后添加一个当前字符串的子串. ...

  8. HDU 5945 题解(DP)(单调队列)

    题面: Fxx and game Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others) T ...

  9. uWSGI、uwsgi、WSGI、之间的关系,为什么要用nginx加uWSGI部署。

    WSGI 协议 WSGI:是一种协议规范,起到规范参数的作用,就像告诉公路一样,规定超车靠右行,速度不低于90km/h,等.但这一切都是对双方进行沟通,比如,重庆到武汉这条高速路,这儿重庆和武汉就各为 ...

  10. Linux性能优化从入门到实战:16 文件系统篇:总结磁盘I/O指标/工具、问题定位和调优

    (1)磁盘 I/O 性能指标 文件系统和磁盘 I/O 指标对应的工具 文件系统和磁盘 I/O 工具对应的指标 (2)磁盘 I/O 问题定位分析思路 (3)I/O 性能优化思路 Step 1:首先采用 ...