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

    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(" ");
    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

  • 相关阅读:
    JVM致命错误日志(hs_err_pid.log)解读
    ant+proguard签名打包 .jar
    ProGuard之——代码混淆
    Java代码加密与反编译(二):用加密算法DES修改classLoader实现对.class文件加密
    利用Ant与Proguard混淆
    Ant在Java项目中的使用(一眼就看会)
    Native2Ascii文件转换 -- 待完善
    scp 的时候提示WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!
    logback与log4j比较
    腾讯、百度、阿里面试经验—(3)阿里面经
  • 原文地址:https://www.cnblogs.com/Jeely/p/10953955.html
Copyright © 2020-2023  润新知