博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
NopCommerce学习(2) EntityFramework
阅读量:5214 次
发布时间:2019-06-14

本文共 20939 字,大约阅读时间需要 69 分钟。

NopCommerce-EntityFramework开发:主要是Controller-Service-Repository的开发方式

操作数据库,主要对象是BaseEntity,IDbContext和NopObjectContext,IRepository和EfRepository,NopEntityTypeConfiguration(可以使用EntityFramework提供的EntityTypeConfiguration不使用NopCommerce拓展的NopEntityTypeConfiguration)
以下代码GitBub地址:https://github.com/heshengli/nop
BaseEntity,实体基类

/// /// Base class for entities/// public abstract partial class BaseEntity{        ///         /// Gets or sets the entity identifier        ///         public int Id { get; set; }        public override bool Equals(object obj)        {            return Equals(obj as BaseEntity);        }        private static bool IsTransient(BaseEntity obj)        {            return obj != null && Equals(obj.Id, default(int));        }        private Type GetUnproxiedType()        {            return GetType();        }        public virtual bool Equals(BaseEntity other)        {            if (other == null)                return false;            if (ReferenceEquals(this, other))                return true;            if (!IsTransient(this) &&                !IsTransient(other) &&                Equals(Id, other.Id))            {                var otherType = other.GetUnproxiedType();                var thisType = GetUnproxiedType();                return thisType.IsAssignableFrom(otherType) ||                        otherType.IsAssignableFrom(thisType);            }            return false;        }        public override int GetHashCode()        {            if (Equals(Id, default(int)))                return base.GetHashCode();            return Id.GetHashCode();        }        public static bool operator ==(BaseEntity x, BaseEntity y)        {            return Equals(x, y);        }        public static bool operator !=(BaseEntity x, BaseEntity y)        {            return !(x == y);        }}

IDbContext,数据上下文接口

public interface IDbContext{        ///         /// Get DbSet        ///         /// 
Entity type
///
DbSet
IDbSet
Set
() where TEntity : BaseEntity; ///
/// Save changes /// ///
int SaveChanges(); ///
/// Execute stores procedure and load a list of entities at the end /// ///
Entity type
///
Command text ///
Parameters ///
Entities
IList
ExecuteStoredProcedureList
(string commandText, params object[] parameters) where TEntity : BaseEntity, new(); ///
/// Creates a raw SQL query that will return elements of the given generic type. The type can be any type that has properties that match the names of the columns returned from the query, or can be a simple primitive type. The type does not have to be an entity type. The results of this query are never tracked by the context even if the type of object returned is an entity type. /// ///
The type of object returned by the query.
///
The SQL query string. ///
The parameters to apply to the SQL query string. ///
Result
IEnumerable
SqlQuery
(string sql, params object[] parameters); ///
/// Executes the given DDL/DML command against the database. /// ///
The command string ///
false - the transaction creation is not ensured; true - the transaction creation is ensured. ///
Timeout value, in seconds. A null value indicates that the default value of the underlying provider will be used ///
The parameters to apply to the command string. ///
The result returned by the database after executing the command.
int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = null, params object[] parameters); ///
/// Detach an entity /// ///
Entity void Detach(object entity); ///
/// Gets or sets a value indicating whether proxy creation setting is enabled (used in EF) /// bool ProxyCreationEnabled { get; set; } ///
/// Gets or sets a value indicating whether auto detect changes setting is enabled (used in EF) /// bool AutoDetectChangesEnabled { get; set; }}

IRepository,基础操作接口

/// /// Repository /// public partial interface IRepository
where T : BaseEntity{ ///
/// Get entity by identifier /// ///
Identifier ///
Entity
T GetById(object id); ///
/// Insert entity /// ///
Entity void Insert(T entity); ///
/// Insert entities /// ///
Entities void Insert(IEnumerable
entities); ///
/// Update entity /// ///
Entity void Update(T entity); ///
/// Update entities /// ///
Entities void Update(IEnumerable
entities); ///
/// Delete entity /// ///
Entity void Delete(T entity); ///
/// Delete entities /// ///
Entities void Delete(IEnumerable
entities); ///
/// Delete entity by id /// ///
void Delete(int id); ///
/// Gets a table /// IQueryable
Table { get; } ///
/// Gets a table with "no tracking" enabled (EF feature) Use it only when you load record(s) only for read-only operations /// IQueryable
TableNoTracking { get; }}

NopObjectContext,继承DbContext, IDbContext,具体实现

/// /// Object context/// public class NopObjectContext : DbContext, IDbContext{        #region Ctor        public NopObjectContext(string nameOrConnectionString)            : base(nameOrConnectionString)        {            //是否开启懒加载            //((IObjectContextAdapter) this).ObjectContext.ContextOptions.LazyLoadingEnabled = true;        }        #endregion        #region Utilities        protected override void OnModelCreating(DbModelBuilder modelBuilder)        {            //dynamically load all configuration            //System.Type configType = typeof(LanguageMap);   //any of your configuration classes here            //var typesToRegister = Assembly.GetAssembly(configType).GetTypes()            var typesToRegister = Assembly.GetExecutingAssembly().GetTypes()            .Where(type => !String.IsNullOrEmpty(type.Namespace))            .Where(type => type.BaseType != null && type.BaseType.IsGenericType &&                type.BaseType.GetGenericTypeDefinition() == typeof(NopEntityTypeConfiguration<>));            //ef自带对象            //var typesToRegister2 = 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)            {                dynamic configurationInstance = Activator.CreateInstance(type);                modelBuilder.Configurations.Add(configurationInstance);            }            //...or do it manually below. For example,            //modelBuilder.Configurations.Add(new LanguageMap());            //移除复数表名的约定            //modelBuilder.Conventions.Remove
(); //检测数据库是否存在 //Database.SetInitializer
(null); base.OnModelCreating(modelBuilder); } ///
/// Attach an entity to the context or return an already attached entity (if it was already attached) /// ///
TEntity
///
Entity ///
Attached entity
protected virtual TEntity AttachEntityToContext
(TEntity entity) where TEntity : BaseEntity, new() { //little hack here until Entity Framework really supports stored procedures //otherwise, navigation properties of loaded entities are not loaded until an entity is attached to the context var alreadyAttached = Set
().Local.FirstOrDefault(x => x.Id == entity.Id); if (alreadyAttached == null) { //attach new entity Set
().Attach(entity); return entity; } //entity is already loaded return alreadyAttached; } #endregion #region Methods ///
/// Create database script /// ///
SQL to generate database
public string CreateDatabaseScript() { return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript(); } ///
/// Get DbSet /// ///
Entity type
///
DbSet
public new IDbSet
Set
() where TEntity : BaseEntity { return base.Set
(); } ///
/// Execute stores procedure and load a list of entities at the end /// ///
Entity type
///
Command text ///
Parameters ///
Entities
public IList
ExecuteStoredProcedureList
(string commandText, params object[] parameters) where TEntity : BaseEntity, new() { //add parameters to command if (parameters != null && parameters.Length > 0) { for (int i = 0; i <= parameters.Length - 1; i++) { var p = parameters[i] as DbParameter; if (p == null) throw new Exception("Not support parameter type"); commandText += i == 0 ? " " : ", "; commandText += "@" + p.ParameterName; if (p.Direction == ParameterDirection.InputOutput || p.Direction == ParameterDirection.Output) { //output parameter commandText += " output"; } } } var result = this.Database.SqlQuery
(commandText, parameters).ToList(); //performance hack applied as described here - http://www.nopcommerce.com/boards/t/25483/fix-very-important-speed-improvement.aspx bool acd = this.Configuration.AutoDetectChangesEnabled; try { this.Configuration.AutoDetectChangesEnabled = false; for (int i = 0; i < result.Count; i++) result[i] = AttachEntityToContext(result[i]); } finally { this.Configuration.AutoDetectChangesEnabled = acd; } return result; } ///
/// Creates a raw SQL query that will return elements of the given generic type. The type can be any type that has properties that match the names of the columns returned from the query, or can be a simple primitive type. The type does not have to be an entity type. The results of this query are never tracked by the context even if the type of object returned is an entity type. /// ///
The type of object returned by the query.
///
The SQL query string. ///
The parameters to apply to the SQL query string. ///
Result
public IEnumerable
SqlQuery
(string sql, params object[] parameters) { return this.Database.SqlQuery
(sql, parameters); } ///
/// Executes the given DDL/DML command against the database. /// ///
The command string ///
false - the transaction creation is not ensured; true - the transaction creation is ensured. ///
Timeout value, in seconds. A null value indicates that the default value of the underlying provider will be used ///
The parameters to apply to the command string. ///
The result returned by the database after executing the command.
public int ExecuteSqlCommand(string sql, bool doNotEnsureTransaction = false, int? timeout = null, params object[] parameters) { int? previousTimeout = null; if (timeout.HasValue) { //store previous timeout previousTimeout = ((IObjectContextAdapter)this).ObjectContext.CommandTimeout; ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = timeout; } var transactionalBehavior = doNotEnsureTransaction ? TransactionalBehavior.DoNotEnsureTransaction : TransactionalBehavior.EnsureTransaction; var result = this.Database.ExecuteSqlCommand(transactionalBehavior, sql, parameters); if (timeout.HasValue) { //Set previous timeout back ((IObjectContextAdapter)this).ObjectContext.CommandTimeout = previousTimeout; } //return result return result; } ///
/// Detach an entity /// ///
Entity public void Detach(object entity) { if (entity == null) throw new ArgumentNullException("entity"); ((IObjectContextAdapter)this).ObjectContext.Detach(entity); } #endregion #region Properties ///
/// Gets or sets a value indicating whether proxy creation setting is enabled (used in EF) /// public virtual bool ProxyCreationEnabled { get { return this.Configuration.ProxyCreationEnabled; } set { this.Configuration.ProxyCreationEnabled = value; } } ///
/// Gets or sets a value indicating whether auto detect changes setting is enabled (used in EF) /// public virtual bool AutoDetectChangesEnabled { get { return this.Configuration.AutoDetectChangesEnabled; } set { this.Configuration.AutoDetectChangesEnabled = value; } } #endregion}

EfRepository,IRepository接口的具体实现

/// /// Entity Framework repository/// public partial class EfRepository
: IRepository
where T : BaseEntity { #region Fields private readonly IDbContext _context; private IDbSet
_entities; #endregion #region Ctor ///
/// Ctor /// ///
Object context public EfRepository(IDbContext context) { this._context = context; } #endregion #region Utilities ///
/// Get full error /// ///
Exception ///
Error
protected string GetFullErrorText(DbEntityValidationException exc) { var msg = string.Empty; foreach (var validationErrors in exc.EntityValidationErrors) foreach (var error in validationErrors.ValidationErrors) msg += string.Format("Property: {0} Error: {1}", error.PropertyName, error.ErrorMessage) + Environment.NewLine; return msg; } #endregion #region Methods ///
/// Get entity by identifier /// ///
Identifier ///
Entity
public virtual T GetById(object id) { //see some suggested performance optimization (not tested) //http://stackoverflow.com/questions/11686225/dbset-find-method-ridiculously-slow-compared-to-singleordefault-on-id/11688189#comment34876113_11688189 return this.Entities.Find(id); } ///
/// Insert entity /// ///
Entity public virtual void Insert(T entity) { try { if (entity == null) throw new ArgumentNullException("entity"); this.Entities.Add(entity); this._context.SaveChanges(); } catch (DbEntityValidationException dbEx) { throw new Exception(GetFullErrorText(dbEx), dbEx); } } ///
/// Insert entities /// ///
Entities public virtual void Insert(IEnumerable
entities) { try { if (entities == null) throw new ArgumentNullException("entities"); foreach (var entity in entities) this.Entities.Add(entity); this._context.SaveChanges(); } catch (DbEntityValidationException dbEx) { throw new Exception(GetFullErrorText(dbEx), dbEx); } } ///
/// Update entity /// ///
Entity public virtual void Update(T entity) { try { if (entity == null) throw new ArgumentNullException("entity"); this._context.SaveChanges(); } catch (DbEntityValidationException dbEx) { throw new Exception(GetFullErrorText(dbEx), dbEx); } } ///
/// Update entities /// ///
Entities public virtual void Update(IEnumerable
entities) { try { if (entities == null) throw new ArgumentNullException("entities"); this._context.SaveChanges(); } catch (DbEntityValidationException dbEx) { throw new Exception(GetFullErrorText(dbEx), dbEx); } } ///
/// Delete entity /// ///
Entity public virtual void Delete(T entity) { try { if (entity == null) throw new ArgumentNullException("entity"); this.Entities.Remove(entity); this._context.SaveChanges(); } catch (DbEntityValidationException dbEx) { throw new Exception(GetFullErrorText(dbEx), dbEx); } } ///
/// Delete entities /// ///
Entities public virtual void Delete(IEnumerable
entities) { try { if (entities == null) throw new ArgumentNullException("entities"); foreach (var entity in entities) this.Entities.Remove(entity); this._context.SaveChanges(); } catch (DbEntityValidationException dbEx) { throw new Exception(GetFullErrorText(dbEx), dbEx); } } public void Delete(int id) { try { T entity = this.Entities.Find(id); if (entity == null) throw new ArgumentNullException("entities"); this.Entities.Remove(entity); this._context.SaveChanges(); } catch (DbEntityValidationException dbEx) { throw new Exception(GetFullErrorText(dbEx), dbEx); } } #endregion #region Properties ///
/// Gets a table /// public virtual IQueryable
Table { get { return this.Entities; } } ///
/// Gets a table with "no tracking" enabled (EF feature) Use it only when you load record(s) only for read-only operations /// public virtual IQueryable
TableNoTracking { get { return this.Entities.AsNoTracking(); } } ///
/// Entities /// protected virtual IDbSet
Entities { get { if (_entities == null) _entities = _context.Set
(); return _entities; } } #endregion}NopEntityTypeConfiguration,可拓展的抽象类public abstract class NopEntityTypeConfiguration
: EntityTypeConfiguration
where T : class{ protected NopEntityTypeConfiguration() { PostInitialize(); } ///
/// Developers can override this method in custom partial classes /// in order to add some custom initialization code to constructors /// protected virtual void PostInitialize() { }}

简单demo:

实体基础代码

public class Student : BaseEntity{        public string Name { get; set; }        public string CustomProperty { get; set; }}/// /// 实体映射表nop拓展/// public partial class StudentMap : NopEntityTypeConfiguration
{ public StudentMap() { this.ToTable("Student"); this.HasKey(pa => pa.Id); this.Property(pa => pa.Name).IsRequired(); }}///
/// 原生ef,需要调整NopObjectContext的代码/// //public partial class StudentMap2 : EntityTypeConfiguration
//{// public StudentMap2()// {// this.ToTable("Student");// this.HasKey(pa => pa.Id);// this.Property(pa => pa.Name).IsRequired();// }//}public interface IStudentService{ void Insert(Student stu); void Update(Student stu); void Delete(int id); IEnumerable
GetList();}public class StudentService : IStudentService{ private readonly IRepository
_iStudentRepository; private readonly IDbContext _iDbContext; public StudentService() { _iDbContext = new NopObjectContext("App"); _iStudentRepository = new EfRepository
(_iDbContext); } //Ioc Autofac 调整 //public StudentService(IRepository
iStudentRepositpory,IDbContext iDbContext) //{ // _iDbContext = iDbContext; // _iStudentRepository = iStudentRepositpory; //} public void Delete(int id) { _iStudentRepository.Delete(id); } public IEnumerable
GetList() { return _iStudentRepository.Table.AsEnumerable(); } public void Insert(Student stu) { _iStudentRepository.Insert(stu); } public void Update(Student stu) { _iStudentRepository.Update(stu); }}

调用代码(使用了简单的consoleApp)

class Program {    private static readonly IStudentService _iStudentService =     new StudentService();    static void Main(string[] args)    {        Student stu = new Student() {                Name="李四",                CustomProperty="自定义属性2"            };            _iStudentService.Insert(stu);            Console.WriteLine(stu.Name+"");            Console.ReadKey();        }}

转载于:https://www.cnblogs.com/heshengli/p/9338784.html

你可能感兴趣的文章
ProjectEuler 9
查看>>
中文编程
查看>>
软件开发方法
查看>>
Dllregisterserver调用失败解决方法
查看>>
Java文件操作大全
查看>>
数据结构&算法实践—【排序|插入排序】插入排序
查看>>
图的应用详解-数据结构
查看>>
WPF中播放视频音频
查看>>
linux下配置固定ip
查看>>
MsSql 游标 修改字段两个表关联 表向另个表插入记录
查看>>
Atlas命名空间Sys.Data下控件介绍——DataColumn,DataRow和DataTable
查看>>
一个简单驱动的makefile
查看>>
《宁夏文学六十年》读后
查看>>
几款实力很强的小工具,提高Windows使用效率
查看>>
hdu 5104 Primes Problem (素数 打表 水)
查看>>
Android 隐式意图激活另外一个Actitity
查看>>
HTML 事件属性_03
查看>>
HADOOP-ORACLE: 装载Hadoop 文件到数据库
查看>>
C# AutoResetEvent 理解
查看>>
【Nutch2.2.1基础教程之6】Nutch2.2.1抓取流程 分类: H...
查看>>