Entiy Framework研究 - 基础设施层

来源:互联网 发布:做广告牌用什么软件 编辑:程序博客网 时间:2024/04/30 21:09

基础设施层主要包含3个项目:

一、数据实体,对应到数据的表和视图

     在这里有个基础实体类,用来限定repository的泛型实体传入,也重载了一些方法hashcode之类的,方便做数据实体比较,还有一个辅助生成主键的类,代码如下:

     1. Entity类

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Chart.Workflow.Infrastructure.Data{    public class Entity    {        #region Members        int? _requestedHashCode;        string _Id;        #endregion        #region Properties        /// <summary>        /// Get the persisten object identifier        /// </summary>        public virtual string Id        {            get            {                return _Id;            }            protected set            {                _Id = value;            }        }        #endregion        #region Public Methods        /// <summary>        /// Check if this entity is transient, ie, without identity at this moment        /// </summary>        /// <returns>True if entity is transient, else false</returns>        public bool IsTransient()        {            return string.IsNullOrEmpty(this.Id);        }        /// <summary>        /// Generate identity for this entity        /// </summary>        public void GenerateNewIdentity()        {            if (IsTransient())                this.Id = IdentityGenerator.NewSequentialId();        }        /// <summary>        /// Change current identity for a new non transient identity        /// </summary>        /// <param name="identity">the new identity</param>        public void ChangeCurrentIdentity(string identity)        {            if (!string.IsNullOrEmpty(this.Id))                this.Id = identity;        }        #endregion        #region Overrides Methods        /// <summary>        /// <see cref="M:System.Object.Equals"/>        /// </summary>        /// <param name="obj"><see cref="M:System.Object.Equals"/></param>        /// <returns><see cref="M:System.Object.Equals"/></returns>        public override bool Equals(object obj)        {            if (obj == null || !(obj is Entity))                return false;            if (Object.ReferenceEquals(this, obj))                return true;            Entity item = (Entity)obj;            if (item.IsTransient() || this.IsTransient())                return false;            else                return item.Id == this.Id;        }        /// <summary>        /// <see cref="M:System.Object.GetHashCode"/>        /// </summary>        /// <returns><see cref="M:System.Object.GetHashCode"/></returns>        public override int GetHashCode()        {            if (!IsTransient())            {                if (!_requestedHashCode.HasValue)                    _requestedHashCode = this.Id.GetHashCode() ^ 31;                 // XOR for random distribution                (http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx)                return _requestedHashCode.Value;            }            else                return base.GetHashCode();        }        public static bool operator ==(Entity left, Entity right)        {            if (Object.Equals(left, null))                return (Object.Equals(right, null)) ? true : false;            else                return left.Equals(right);        }        public static bool operator !=(Entity left, Entity right)        {            return !(left == right);        }        #endregion    }}

     2. IdentityGenerator类

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Chart.Workflow.Infrastructure.Data{    public static class IdentityGenerator    {        /// <summary>        /// This algorithm generates secuential strings across system boundaries, ideal for databases         /// </summary>        /// <returns></returns>        public static string NewSequentialId()        {            string resut = Guid.NewGuid().ToString().Replace("-", "");            return resut;        }        /// <summary>        /// This algorithm generates secuential strings across system boundaries, ideal for databases         /// </summary>        /// <returns></returns>        public static Guid NewSequentialGuid()        {            byte[] uid = Guid.NewGuid().ToByteArray();            byte[] binDate = BitConverter.GetBytes(DateTime.UtcNow.Ticks);            byte[] secuentialGuid = new byte[uid.Length];            secuentialGuid[0] = uid[0];            secuentialGuid[1] = uid[1];            secuentialGuid[2] = uid[2];            secuentialGuid[3] = uid[3];            secuentialGuid[4] = uid[4];            secuentialGuid[5] = uid[5];            secuentialGuid[6] = uid[6];            // set the first part of the 8th byte to '1100' so                 // later we'll be able to validate it was generated by us               secuentialGuid[7] = (byte)(0xc0 | (0xf & uid[7]));            // the last 8 bytes are sequential,                // it minimizes index fragmentation               // to a degree as long as there are not a large                // number of Secuential-Guids generated per millisecond              secuentialGuid[9] = binDate[0];            secuentialGuid[8] = binDate[1];            secuentialGuid[15] = binDate[2];            secuentialGuid[14] = binDate[3];            secuentialGuid[13] = binDate[4];            secuentialGuid[12] = binDate[5];            secuentialGuid[11] = binDate[6];            secuentialGuid[10] = binDate[7];            return new Guid(secuentialGuid);        }    }}


二、辅助切面,主要用来全局的东西:包含验证,日志,资源之类的;

      基础方法如下:

三、数据上下文,主要是基础的数据访问操作实现

     1. ISql接口,做sql语句查询使用,如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Chart.Workflow.Infrastructure.Context{    public interface ISql    {        IEnumerable<TEntity> ExecuteQuery<TEntity>(string sqlQuery, params object[] parameters);        int ExecuteCommand(string sqlCommand, params object[] parameters);    }}

     2. IQueryUnitOfWork类,简单数据的操作,如下:

using System;using System.Collections.Generic;using System.Data.Entity;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Chart.Workflow.Infrastructure.Context{    public interface IQueryUnitOfWork:IUnitOfWork,ISql    {        DbSet<TEntity> CreateSet<TEntity>() where TEntity : class;        void Attach<TEntity>(TEntity item) where TEntity : class;        void SetModified<TEntity>(TEntity item) where TEntity : class;        void ApplyCurrentValues<TEntity>(TEntity original, TEntity current) where TEntity : class;    }}

     3. IUnitOfWork接口,数据事务性操作,如下:

using System;using System.Collections.Generic;using System.Data.Entity;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Chart.Workflow.Infrastructure.Context{    public interface IUnitOfWork : IDisposable    {        void Commit();        void CommitAndRefreshChanges();        void RollbackChanges();    }}

     4. UnitOfWork类,具体核心实现数据操作,如下:

using Chart.Workflow.Infrastructure.Data;using System;using System.Collections.Generic;using System.Data.Entity;using System.Data.Entity.Infrastructure;using System.Data.Entity.ModelConfiguration.Conventions;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Chart.Workflow.Infrastructure.Context{    public class UnitOfWork : DbContext, IQueryUnitOfWork    {        IDbSet<Student> _students;        public IDbSet<Student> Students        {            get            {                if (_students == null)                    _students = base.Set<Student>();                return _students;            }        }        IDbSet<Course> _course;        public IDbSet<Course> Courses        {            get            {                if (_course == null)                    _course = base.Set<Course>();                return _course;            }        }        public UnitOfWork()            :base()        {        }        public UnitOfWork(string connectionstring)            :base(connectionstring)        {        }        #region IQueryUnitOfWork Members        public DbSet<TEntity> CreateSet<TEntity>() where TEntity : class        {            return base.Set<TEntity>();        }        public void Attach<TEntity>(TEntity item) where TEntity : class        {            //attach and set as unchanged            base.Entry<TEntity>(item).State = System.Data.EntityState.Unchanged;        }        public void SetModified<TEntity>(TEntity item) where TEntity : class        {            //this operation also attach item in object state manager            base.Entry<TEntity>(item).State = System.Data.EntityState.Modified;        }        public void ApplyCurrentValues<TEntity>(TEntity original, TEntity current) where TEntity : class        {            //if it is not attached, attach original and set current values            base.Entry<TEntity>(original).CurrentValues.SetValues(current);        }        public void Commit()        {            base.SaveChanges();        }        public void CommitAndRefreshChanges()        {            bool saveFailed = false;            do            {                try                {                    base.SaveChanges();                    saveFailed = false;                }                catch (DbUpdateConcurrencyException ex)                {                    saveFailed = true;                    ex.Entries.ToList()                              .ForEach(entry =>                              {                                  entry.OriginalValues.SetValues(entry.GetDatabaseValues());                              });                }            } while (saveFailed);        }        public void RollbackChanges()        {            // set all entities in change tracker             // as 'unchanged state'            base.ChangeTracker.Entries()                              .ToList()                              .ForEach(entry => entry.State = System.Data.EntityState.Unchanged);        }        public IEnumerable<TEntity> ExecuteQuery<TEntity>(string sqlQuery, params object[] parameters)        {            if (parameters == null)            {                parameters = new object[0];            }            return base.Database.SqlQuery<TEntity>(sqlQuery, parameters);        }        public int ExecuteCommand(string sqlCommand, params object[] parameters)        {            if (parameters == null)            {                parameters = new object[0];            }            return base.Database.ExecuteSqlCommand(sqlCommand, parameters);        }        #endregion        #region DbContext Overrides        protected override void OnModelCreating(DbModelBuilder modelBuilder)        {            //Remove unused conventions            //OneToManyCascadeDeleteConvention            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();            //数据库表和实体类型不一致使用            modelBuilder.Entity<Student>().ToTable("Student");            modelBuilder.Entity<Course>().ToTable("Course");            //数据库字段条件限制配置文件            modelBuilder.Configurations.Add(new StudentEntityTypeConfiguration());            modelBuilder.Configurations.Add(new CourseEntityTypeConfiguration());        }        #endregion    }}
原创粉丝点击