using System; using System.Collections.Generic; using System.Linq; using System.Text; using EMIS.Entities.HRServices; using EMIS.Utility.Log; using System.Data.Entity.Validation; using System.Linq.Expressions; using System.Reflection; using System.Data.Entity.Infrastructure; using System.Data.Entity.Core.Metadata.Edm; using System.Data; using System.Collections; using Bowin.Common.Linq; using System.Data.SqlClient; using Bowin.Common.Linq.DB; using System.Configuration; using System.Data.Entity; using Bowin.Common.Linq.Entity; using System.Diagnostics; namespace EMIS.DataLogic { public class HRUnitOfWork : HRServiceContextContainer, IDisposable { public HRUnitOfWork() : base("HRServiceContextContainer") { } public TEntity Add(TEntity entity) where TEntity : class { return Set().Add(entity); } public IEnumerable AddRange(IEnumerable entityList) where TEntity : class { return Set().AddRange(entityList); } public TEntity Attach(TEntity entity) where TEntity : class { return Set().Attach(entity); } /// /// 事务提交 /// public void Commit() { var logs = DbLog.GetLog(this.ChangeTracker).Concat( DbLog.GetRelationshipLog(this)).ToList(); try { SaveChanges(); logs.ForEach(x => x.IsSuccess = true); LogUnitOfWork.WriteLogs(logs); } catch (DbEntityValidationException dbEx) { logs.ForEach(x => x.IsSuccess = false); LogUnitOfWork.WriteLogs(logs); foreach (var validationErrors in dbEx.EntityValidationErrors) { foreach (var validationError in validationErrors.ValidationErrors) { Trace.TraceInformation("Property: {0} Error: {1}", validationError.PropertyName, validationError.ErrorMessage); } } throw dbEx; } catch (Exception ex) { logs.ForEach(x => x.IsSuccess = false); LogUnitOfWork.WriteLogs(logs); throw ex; } } public void BulkInsert(IList data) where TEntity : class { var logList = DbLog.GetBulkInsertLog(data); try { var db = GetConnection(); data.ExecuteBulkCopy(db, typeof(TEntity).Name); logList.ForEach(x => x.IsSuccess = true); LogUnitOfWork.WriteLogs(logList); } catch (Exception ex) { logList.ForEach(x => x.IsSuccess = false); LogUnitOfWork.WriteLogs(logList); throw ex; } } public void BulkInsert(IList data, Expression> relationShip) { if (!typeof(TProperty).FullName.Contains("HashSet")) { return; } var tableName1 = typeof(TEntity).Name; var targetProperty = (PropertyInfo)((MemberExpression)relationShip.Body).Member; var tableName2 = targetProperty.Name; var metadata = ((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace; var associationSet = metadata.GetItemCollection(DataSpace.SSpace) .GetItems().Single() .AssociationSets.Where(x => x.AssociationSetEnds.Any(w => w.Name == tableName1) && (x.AssociationSetEnds.Any(w => w.Name == tableName1 + tableName2) || x.AssociationSetEnds.Any(w => w.Name == tableName2 + tableName1))).FirstOrDefault(); if (associationSet == null) { return; } bool isSourceSet; var targetSetProperty = typeof(AssociationSet).GetProperty("TargetSet", BindingFlags.Instance | BindingFlags.NonPublic); var sourceSetProperty = typeof(AssociationSet).GetProperty("SourceSet", BindingFlags.Instance | BindingFlags.NonPublic); var targetSet = ((System.Data.Entity.Core.Metadata.Edm.EntitySet)(targetSetProperty.GetValue(associationSet, null))); var sourceSet = ((System.Data.Entity.Core.Metadata.Edm.EntitySet)(sourceSetProperty.GetValue(associationSet, null))); var tableName = targetSet.Table; if (tableName == null) { tableName = sourceSet.Table; isSourceSet = false; if (tableName == null || tableName == tableName1) { return; } } else { isSourceSet = true; } var targetElementType = (typeof(TProperty)).GetGenericArguments()[0]; var key1 = TableKeyDictionary.GetKeyName(); var key2 = TableKeyDictionary.GetKeyName(targetElementType.Assembly.CreateInstance(targetElementType.FullName)); var keyProperty = typeof(TEntity).GetProperty(key1); var targetKeyPropery = targetElementType.GetProperty(key2); var resultTable = new DataTable(tableName); var db = GetConnection(); var columnList = db.GetTableColumns(tableName); if (columnList.First().ToLower() == key1.ToLower()) { resultTable.Columns.Add(key1, typeof(Guid)); resultTable.Columns.Add(key2, typeof(Guid)); } else { resultTable.Columns.Add(key2, typeof(Guid)); resultTable.Columns.Add(key1, typeof(Guid)); } foreach (var dataItem in data) { IEnumerable targetHashset = (IEnumerable)targetProperty.GetValue(dataItem, null); foreach (var target in targetHashset) { var row = resultTable.NewRow(); if (columnList.First().ToLower() == key1.ToLower()) { row[0] = (Guid)keyProperty.GetValue(dataItem, null); row[1] = (Guid)targetKeyPropery.GetValue(target, null); } else { row[0] = (Guid)targetKeyPropery.GetValue(target, null); row[1] = (Guid)keyProperty.GetValue(dataItem, null); } resultTable.Rows.Add(row); } } var logList = DbLog.GetBulkInsertLog(resultTable, tableName); try { BulkCopyExtensions.ExecuteBulkCopy(db, resultTable); logList.ForEach(x => x.IsSuccess = true); LogUnitOfWork.WriteLogs(logList); } catch (Exception ex) { logList.ForEach(x => x.IsSuccess = false); LogUnitOfWork.WriteLogs(logList); throw ex; } } private SqlConnection GetConnection() { var connectionKey = typeof(HRServiceContextContainer).Name; if (SqlConnectionManager.IsGlobalConnectionStarted) { return SqlConnectionManager.GetConnection(connectionKey); } else { return new SqlConnection(ConfigurationManager.ConnectionStrings[connectionKey].ConnectionString); } } public TEntity Remove(TEntity entity) where TEntity : class { Set().Attach(entity); return Set().Remove(entity); } public void Remove(Expression> where) where TEntity : class { var entities = this.Set().Where(where).ToList(); Set().RemoveRange(entities); } public void RemoveRange(HashSet entities) where TEntity : class { Set().RemoveRange(entities); } void IDisposable.Dispose() { Dispose(); } public void Update(TEntity entity) where TEntity : class { Entry(entity).State = System.Data.Entity.EntityState.Modified; } public event Action PostUpdate; public void Update(Expression> setExpression, Expression> whereExpression) where TEntity : class { var entities = this.Set().Where(whereExpression).ToList(); entities.ForEach(x => { //var updateObj = setExpression.Compile().Invoke(x); //this.Attach(x); foreach (var binding in ((MemberInitExpression)setExpression.Body).Bindings) { PropertyInfo property = (PropertyInfo)binding.Member; var expression = ((MemberAssignment)binding).Expression; if (expression is ConstantExpression) { property.SetValue(x, ((ConstantExpression)expression).Value, null); } else { property.SetValue(x, Expression.Lambda(expression, setExpression.Parameters.ToArray()).Compile() .DynamicInvoke(x), null); } } if (PostUpdate != null) { var @event = PostUpdate; @event(x); } }); this.Commit(); } public void Delete(Expression> whereExpression) where TEntity : class { var entities = this.Set().Where(whereExpression).ToList(); var logList = DbLog.GetDeleteLog(entities); try { ((DbContext)this).Delete(whereExpression); logList.ForEach(x => x.IsSuccess = true); LogUnitOfWork.WriteLogs(logList); } catch (Exception ex) { logList.ForEach(x => x.IsSuccess = false); LogUnitOfWork.WriteLogs(logList); throw ex; } //entities.ForEach(x => this.Remove(x)); //this.Commit(); } public void Delete(TEntity entity, Expression> relationShip) { if (!typeof(TProperty).FullName.Contains("HashSet")) { return; } var tableName1 = typeof(TEntity).Name; var targetProperty = (PropertyInfo)((MemberExpression)relationShip.Body).Member; var tableName2 = targetProperty.Name; var metadata = ((IObjectContextAdapter)this).ObjectContext.MetadataWorkspace; var associationSet = metadata.GetItemCollection(DataSpace.SSpace) .GetItems().Single() .AssociationSets.Where(x => x.AssociationSetEnds.Any(w => w.Name == tableName1) && (x.AssociationSetEnds.Any(w => w.Name == tableName1 + tableName2) || x.AssociationSetEnds.Any(w => w.Name == tableName2 + tableName1))).FirstOrDefault(); if (associationSet == null) { return; } bool isSourceSet; var targetSetProperty = typeof(AssociationSet).GetProperty("TargetSet", BindingFlags.Instance | BindingFlags.NonPublic); var sourceSetProperty = typeof(AssociationSet).GetProperty("SourceSet", BindingFlags.Instance | BindingFlags.NonPublic); var targetSet = ((System.Data.Entity.Core.Metadata.Edm.EntitySet)(targetSetProperty.GetValue(associationSet, null))); var sourceSet = ((System.Data.Entity.Core.Metadata.Edm.EntitySet)(sourceSetProperty.GetValue(associationSet, null))); var tableName = targetSet.Table; if (tableName == null) { tableName = sourceSet.Table; isSourceSet = false; if (tableName == null || tableName == tableName1) { return; } } else { isSourceSet = true; } var targetElementType = (typeof(TProperty)).GetGenericArguments()[0]; var key1 = TableKeyDictionary.GetKeyName(); var key2 = TableKeyDictionary.GetKeyName(targetElementType.Assembly.CreateInstance(targetElementType.FullName)); var keyProperty = typeof(TEntity).GetProperty(key1); var targetKeyPropery = targetElementType.GetProperty(key2); var resultTable = new DataTable(tableName); if (isSourceSet) { resultTable.Columns.Add(key1, typeof(Guid)); resultTable.Columns.Add(key2, typeof(Guid)); } else { resultTable.Columns.Add(key2, typeof(Guid)); resultTable.Columns.Add(key1, typeof(Guid)); } IEnumerable targetHashset = (IEnumerable)targetProperty.GetValue(entity, null); foreach (var target in targetHashset) { var row = resultTable.NewRow(); if (isSourceSet) { row[0] = (Guid)keyProperty.GetValue(entity, null); row[1] = (Guid)targetKeyPropery.GetValue(target, null); } else { row[0] = (Guid)targetKeyPropery.GetValue(target, null); row[1] = (Guid)keyProperty.GetValue(entity, null); } resultTable.Rows.Add(row); } var logList = DbLog.GetDeleteLog(resultTable, tableName); try { var db = GetConnection(); db.Delete(tableName, key1, (Guid)keyProperty.GetValue(entity, null)); logList.ForEach(x => x.IsSuccess = true); LogUnitOfWork.WriteLogs(logList); } catch (Exception ex) { logList.ForEach(x => x.IsSuccess = false); LogUnitOfWork.WriteLogs(logList); throw ex; } } int ExecuteSQL(string sql, params object[] parameters) { return this.Database.ExecuteSqlCommand(sql, parameters); } public void BatchUpdate(string tableName, string columnName, object value, IList idList) { var assembly = typeof(HRServiceContextContainer).Assembly; var entityType = assembly.GetTypes().Where(x => x.Name.ToLower() == tableName.ToLower()).FirstOrDefault(); var methodInfo = typeof(UnitOfWork).GetMethods() .Where(x => x.ContainsGenericParameters && x.GetGenericArguments().Length == 2 && x.Name == "BatchUpdate").FirstOrDefault(); methodInfo = methodInfo .MakeGenericMethod(entityType, typeof(TKey)); methodInfo.Invoke(this, new object[] { columnName, value, idList }); } public void BatchUpdate(string columnName, object value, IList idList) where TEntity : class { ExpressionFactory factory = new ExpressionFactory(Set()); var para = Expression.Parameter(typeof(TEntity)); var property = typeof(TEntity).GetProperty(columnName); var newExpression = Expression.New(typeof(TEntity).GetConstructor(new Type[] { })); var bindExpression = Expression.Bind(property, GetValueExpression(value, property)); var memberExpression = Expression.MemberInit(newExpression, new MemberBinding[] { bindExpression }); Expression> setExpression = Expression.Lambda>(memberExpression, para); Expression> whereExpression = factory.DynamicInExpression(TableKeyDictionary.GetKeyName(), idList); this.Update(setExpression, whereExpression); } private Expression GetValueExpression(object value, PropertyInfo property) { if (property.PropertyType == typeof(Guid) || property.PropertyType == typeof(Guid?)) { return Expression.Constant(Guid.Parse(value.ToString())); } else if (property.PropertyType == typeof(int) || property.PropertyType == typeof(int?)) { return Expression.Constant(int.Parse(value.ToString())); } else if (property.PropertyType == typeof(short) || property.PropertyType == typeof(short?)) { return Expression.Constant(short.Parse(value.ToString())); } else if (property.PropertyType == typeof(bool) || property.PropertyType == typeof(bool?)) { return Expression.Constant(bool.Parse(value.ToString())); } else if (property.PropertyType == typeof(decimal) || property.PropertyType == typeof(decimal?)) { return Expression.Constant(decimal.Parse(value.ToString())); } else if (property.PropertyType == typeof(DateTime) || property.PropertyType == typeof(DateTime?)) { return Expression.Constant(DateTime.Parse(value.ToString())); } else { return Expression.Convert(Expression.Constant(value), property.PropertyType); } } } }