在上一篇中,我列举了框架的整体结构,下面我们将一一说明:
首先需要说明的是TinyFrame.Data。
它主要用于处理数据库底层操作。包含EF CodeFirst,Repository,Unitofwork三个部分。
其中,DomainModel主要是用来存放实体类的:
1: namespace TinyFrame.Data.DomainModel
2: {
3: public class Book
4: {
5: public int ID { get; set; }
6: public string Name { get; set; }
7: public string Author { get; set; }
8: public string Publishment { get; set; }
9: public int BookTypeID { get; set; }
10: public int BookPlaceID { get; set; }
11:
12: public virtual BookType BookType { get; set; }
13: public virtual BookPlace BookPlace { get; set; }
14: }
15: }
然后,在DomainMapper中,则主要处理数据库字段属性和主外键映射:
1: using System.Data.Entity.ModelConfiguration;
2: using System.ComponentModel.DataAnnotations.Schema;
3: using TinyFrame.Data.DomainModel;
4:
5: namespace TinyFrame.Data.DomainMapper
6: {
7: public class BookMapper:EntityTypeConfiguration<Book>
8: {
9: public BookMapper()
10: {
11: this.ToTable("Book");
12:
13: this.HasKey(c => c.ID);
14: this.Property(c => c.ID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
15: this.Property(c => c.ID).IsRequired();
16:
17: this.Property(c => c.Name).HasMaxLength(255);
18: this.Property(c => c.Name).IsRequired();
19:
20: this.Property(c => c.Author).HasMaxLength(255);
21: this.Property(c => c.Author).IsOptional();
22:
23: this.Property(c => c.Publishment).HasMaxLength(255);
24: this.Property(c => c.Publishment).IsRequired();
25:
26: this.HasRequired(c => c.BookType).WithMany().HasForeignKey(s => s.BookTypeID).WillCascadeOnDelete(false);
27: this.HasRequired(c => c.BookPlace).WithMany().HasForeignKey(s => s.BookPlaceID).WillCascadeOnDelete(false);
28:
29: }
30: }
31: }
上面的代码中,ToTable方法适用于生成数据库新表;HasKey方法则指定主键;Property方法则用于设置字段属性;至于最后两句则主要用于设定主外键映射的,这里我们不做过多讲解。
最后在DataContext中,我们需要进行配置:
1: using System;
2: using System.Data.Entity;
3: using System.Data.Entity.Validation;
4: using TinyFrame.Data.DomainModel;
5: using TinyFrame.Data.DomainMapper;
6:
7: namespace TinyFrame.Data.DataContext
8: {
9: public class BookContext : DbContext, IDbContext
10: {
11: public BookContext()
12: : base("BookConnection")
13: {
14: Configuration.ProxyCreationEnabled = false;
15: Configuration.LazyLoadingEnabled = true;
16: Database.SetInitializer(new MigrateDatabaseToLatestVersion<BookContext, BookContextMConfig>());
17: }
18:
19: public DbSet<Book> Books { get; set; }
20: public DbSet<Student> Students { get; set; }
21: public DbSet<BookLend> BookLends { get; set; }
22: public DbSet<BookType> BookTypes { get; set; }
23: public DbSet<BookPlace> BookPlaces { get; set; }
24: public DbSet<Manager> Managers { get; set; }
25:
26: protected override void OnModelCreating(DbModelBuilder modelBuilder)
27: {
28: modelBuilder.Configurations.Add(new BookMapper());
29: modelBuilder.Configurations.Add(new BookLendMapper());
30: modelBuilder.Configurations.Add(new BookTypeMapper());
31: modelBuilder.Configurations.Add(new BookPlaceMapper());
32: modelBuilder.Configurations.Add(new StudentMapper());
33: modelBuilder.Configurations.Add(new ManagerMapper());
34: base.OnModelCreating(modelBuilder);
35: }
36:
37: public new IDbSet<T> Set<T>() where T : class
38: {
39: return base.Set<T>();
40: }
41: }
42: }
这里说明一下,OnModelCreating主要用于配置数据库实体类映射,我们可以把自定义的配置添加进来,最后通过调用OnModelCreating方法来触发数据库表创建事件。
至于Repository模式,则主要提供数据操作集合:
1: using System;
2: using System.Linq;
3: using System.Linq.Expressions;
4:
5: namespace TinyFrame.Data.DataRepository
6: {
7: public interface IRepository<T> where T:class
8: {
9: T GetByID(long id);
10: T GetByID(int id);
11: T GetByID(Guid id);
12: T GetByID(string id);
13: T Get(Expression<Func<T, bool>> where);
14: IQueryable<T> GetMany(Expression<Func<T, bool>> where);
15:
16: void Insert(T entity);
17: void Update(T entity);
18: void Delete(T entity);
19: void Delete(Expression<Func<T, bool>> where);
20: }
21: }
其具体的实现如下:
1: using System;
2: using System.Linq;
3: using System.Data.Entity;
4: using System.Linq.Expressions;
5: using System.Data.Entity.Validation;
6: using TinyFrame.Data.DataContext;
7:
8: namespace TinyFrame.Data.DataRepository
9: {
10: public class Repository<T>:IRepository<T> where T:class
11: {
12: public Repository(IDbContext context)
13: {
14: this.context = context;
15: }
16:
17: private IDbContext context;
18:
19: private IDbSet<T> dbset;
20: public virtual IDbSet<T> DbSet
21: {
22: get
23: {
24: if (dbset == null)
25: dbset = context.Set<T>();
26: return dbset;
27: }
28: }
29:
30: public virtual T GetByID(long id)
31: {
32: return DbSet.Find(id);
33: }
34:
35: public virtual T GetByID(int id)
36: {
37: return DbSet.Find(id);
38: }
39:
40: public virtual T GetByID(Guid id)
41: {
42: return DbSet.Find(id);
43: }
44:
45: public virtual T GetByID(string id)
46: {
47: return DbSet.Find(id);
48: }
49:
50: public virtual T Get(Expression<Func<T, bool>> where)
51: {
52: return DbSet.Where(where).FirstOrDefault<T>();
53: }
54:
55: public virtual IQueryable<T> GetMany(Expression<Func<T, bool>> where)
56: {
57: return DbSet.Where(where);
58: }
59:
60: public virtual void Insert(T entity)
61: {
62: try
63: {
64: if (entity == null)
65: throw new ArgumentException("实体类为空");
66: DbSet.Add(entity);
67: context.SaveChanges();
68: }
69: catch (DbEntityValidationException dbex)
70: {
71: var msg = string.Empty;
72: foreach(var validationErrors in dbex.EntityValidationErrors)
73: foreach(var validateionError in validationErrors.ValidationErrors)
74: msg+=string.Format("Property:{0} Error:{1}",validateionError.PropertyName,validateionError.ErrorMessage);
75:
76: var fail = new Exception(msg,dbex);
77: throw fail;
78: }
79: }
80:
81: public virtual void Update(T entity)
82: {
83: try
84: {
85: if (entity == null)
86: throw new ArgumentNullException("实体类为空");
87: context.SaveChanges();
88: }
89: catch (DbEntityValidationException dbex)
90: {
91: var msg = string.Empty;
92: foreach (var validationErrors in dbex.EntityValidationErrors)
93: foreach (var validateionError in validationErrors.ValidationErrors)
94: msg += string.Format("Property:{0} Error:{1}", validateionError.PropertyName, validateionError.ErrorMessage);
95:
96: var fail = new Exception(msg, dbex);
97: throw fail;
98: }
99: }
100:
101: public virtual void Delete(T entity)
102: {
103: try
104: {
105: if (entity == null)
106: throw new ArgumentNullException("实体类为空");
107: DbSet.Remove(entity);
108: context.SaveChanges();
109: }
110: catch (DbEntityValidationException dbex)
111: {
112: var msg = string.Empty;
113: foreach (var validationErrors in dbex.EntityValidationErrors)
114: foreach (var validateionError in validationErrors.ValidationErrors)
115: msg += string.Format("Property:{0} Error:{1}", validateionError.PropertyName, validateionError.ErrorMessage);
116:
117: var fail = new Exception(msg, dbex);
118: throw fail;
119: }
120: }
121:
122: public virtual void Delete(Expression<Func<T, bool>> where)
123: {
124: try
125: {
126: var entities = DbSet.Where(where);
127: foreach (var entity in entities.ToList())
128: DbSet.Remove(entity);
129: context.SaveChanges();
130: }
131: catch (DbEntityValidationException dbex)
132: {
133: var msg = string.Empty;
134: foreach (var validationErrors in dbex.EntityValidationErrors)
135: foreach (var validateionError in validationErrors.ValidationErrors)
136: msg += string.Format("Property:{0} Error:{1}", validateionError.PropertyName, validateionError.ErrorMessage);
137:
138: var fail = new Exception(msg, dbex);
139: throw fail;
140: }
141: }
142: }
143: }
由于在编码中,我们使用了泛型对象,所以让数据库中有表变动的时候,不会影响到我们这层。
最后是Unitofwork,这个比较简单,主要用于事务控制:
1: namespace TinyFrame.Data.DataUnitOfWork
2: {
3: public interface IUnitOfWork
4: {
5: void Commit();
6: }
7: }
一旦有批量的数据CRUD的时候,我们可以调用此方法进行批量提交,这样能够保证CRUD的准确性。