初次學習EF的時候,在網上收集了不少資料,但很少有對EF系統的介紹和例子,比如如何通過EF對實體模型進行AMD.這使得我不得不自己去研究和實驗,通過反覆的測試,總算摸索了一些方法,今天把代碼粘貼出來以供大家指點和批評。
public interface IOperate<TEntity>
{
#region 屬性
/// <summary>
/// 獲取 當前實體的查詢數據集
/// </summary>
IQueryable<TEntity> Entities { get; }
#endregion
void Dispose();
#region 新 增
/// <summary>
/// 新增一條數據
/// </summary>
/// <param name="entities"></param>
/// <returns></returns>
int Insert(TEntity entities);
/// <summary>
/// 添加一條記錄並返回實體
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
TEntity InsertAndLoadTEntity(TEntity entity);
/// <summary>
/// 新增多條記錄
/// </summary>
/// <param name="entities"></param>
/// <returns></returns>
int InsertRange(IEnumerable<TEntity> entities);
#endregion
#region 修 改
/// <summary>
/// 修改整個實體
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
int Update(TEntity entity);
/// <summary>
/// 根據表達式參數,按需修改實體
/// </summary>
/// <param name="propertyExpression"></param>
/// <returns></returns>
int Update(Expression<Func<TEntity, TEntity>> propertyExpression);
/// <summary>
/// 根據條件修改(***擴展方法***)
/// </summary>
/// <param name="filterExpression"></param>
/// <param name="updateExpression"></param>
/// <returns></returns>
int Update(Expression<Func<TEntity, bool>> filterExpression, Expression<Func<TEntity, TEntity>> updateExpression);
#endregion
#region 刪 除
/// <summary>
/// 根據條件刪除數據(***擴展方法***)
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
int Delete(Expression<Func<TEntity, bool>> predicate);
/// <summary>
/// 刪除實體,只需要主鍵
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
int Delete(TEntity entity);
/// <summary>
/// 刪除多條記錄
/// </summary>
/// <param name="entities"></param>
/// <returns></returns>
int DeleteRange(IEnumerable<TEntity> entities);
#endregion
#region 執行語句
int ExecuteSqlCommand(string sql, object[] paras);
List<TEntity> SqlQuery(string queryCmdStr, object[] paras);
#endregion
---------------------------------------------以下爲實現接口類--------------------------------------
public class EfOperate<TEntity> : IOperate<TEntity> where TEntity : class, new()
{
private readonly string _dbContextString;
/// <summary>
/// 構造函數
/// </summary>
/// <param name="dbContext"></param>
public EfOperate(string dbContext)
{
_dbContextString = dbContext;
}
private DbContext _dbContext;
/// <summary>
/// 獲得數據庫鏈接的上下文
/// </summary>
public DbContext GetContext
{
get
{
//這裏說明一下,爲什麼Dispose()後,又要設置爲Null,因爲Dispose後,實例並沒有變爲Null,這樣再下一次使用時,無法又要重新實例化。
if (_dbContext == null)
{
if (string.IsNullOrEmpty(_dbContextString))
throw new Exception("傳入的DbConnect爲Null");
_dbContext= DbContexts.GetDbContext(_dbContextString);
}
return _dbContext;
}
}
public void Dispose()
{
if (_dbContext == null) return;
_dbContext.Dispose();
//這裏說明一下,爲什麼Dispose()後,又要設置爲Null,因爲Dispose後,實例並沒有變爲Null,爲了讓實例不再重新實例化特設置爲Null。結合獲取_dbContext實例看更直觀些。
_dbContext = null;
}
#region 集 合
public IQueryable<TEntity> Entities
{
get
{
return GetContext.Set<TEntity>();//此時EF還沒有去真正的執行Sql語句,當ToList()的時候纔會把翻譯成sql語句(也即select)去操作數據庫
}
}
#endregion
#region 添 加
public int Insert(TEntity entity)
{
GetContext.Set<TEntity>().Add(entity);
int rtnNumber= GetContext.SaveChanges();
Dispose();
return rtnNumber;
}
public TEntity InsertAndLoadTEntity(TEntity entity)
{
EntityState state = GetContext.Entry(entity).State;
if (state == EntityState.Detached)
{
GetContext.Entry(entity).State = EntityState.Added;
}
GetContext.SaveChanges();
Dispose();
return entity;
}
/// <summary>
/// 添加多條記錄
/// </summary>
/// <param name="entities"></param>
/// <returns></returns>
public int InsertRange(IEnumerable<TEntity> entities)
{
try
{
GetContext.Set<TEntity>().AddRange(entities);
int rtnNumber = GetContext.SaveChanges();
// _dbContext.Dispose()後,實例並沒有變爲Null,
Dispose();
return rtnNumber;
}
catch (Exception error)
{
throw new Exception(error.Message);
}
}
#endregion
#region 修 改
/// <summary>
/// 缺點:必須在從數據庫加載後的基礎上修改,而不能對一個new的對象進行修改(即便設置了主鍵)
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public int Update(TEntity entity)
{
var entry = GetContext.Entry(entity);
if (entry.State == EntityState.Detached)
{
GetContext.Set<TEntity>().Attach(entity);
entry.State = EntityState.Modified;
}
int rtnNumber = GetContext.SaveChanges();
Dispose();
return rtnNumber;
}
/// <summary>
/// 優點:不需要從數據庫中再加載一次,可對部分字段修改;
/// 缺點:必須設置此數據的主鍵值,否則系統報錯
/// 例子:UpdateUserPart(o=>new Sys_User{Id=user.Id, Code = user.Code,PreIpAddress = user.PreIpAddress});
/// </summary>
/// <param name="propertyExpression"></param>
/// <returns></returns>
public int Update(Expression<Func<TEntity, TEntity>> propertyExpression)
{
try
{
var memberInitExpression = propertyExpression.Body as MemberInitExpression;
var entity = EntityHelper.CopyPropertyValue(propertyExpression);
DbEntityEntry<TEntity> entry = GetContext.Entry(entity);
entry.State = EntityState.Unchanged;
if (memberInitExpression != null)
foreach (var memberInfo in memberInitExpression.Bindings)
{
string propertyName = memberInfo.Member.Name;
entry.Property(propertyName).IsModified = true;
}
GetContext.Configuration.ValidateOnSaveEnabled = false;
}
finally
{
GetContext.Configuration.AutoDetectChangesEnabled = true;
}
int rtnNumber = GetContext.SaveChanges();
Dispose();
return rtnNumber;
}
/// <summary>
/// 修改-擴展方法
/// 可根據條件修改多條記錄的部分字段
/// _provider.Update(o =>o.Password.EndsWith("DDD"),o=>new Sys_User{Code = "RDTS"});
/// 表示滿足Password字段以DDD結尾的記錄,修改其字段Code的值爲傳遞過來的RDTS
/// </summary>
/// <param name="filterExpression">要修改的記錄的條件表達式,若直接爲true,則表示全部滿足要修改的記錄</param>
/// <param name="updateExpression">要修改的部分字段表達式</param>
/// <returns></returns>
public int Update(Expression<Func<TEntity, bool>> filterExpression, Expression<Func<TEntity, TEntity>> updateExpression)
{
int rtnNumber = GetContext.Set<TEntity>().Where(filterExpression).Update(updateExpression);
Dispose();
return rtnNumber;
}
#endregion
#region 刪 除
public int Delete(TEntity entity)
{
#region 方法1 已測試 直接刪除,優點:使用任何類,把記錄直接添加到上下文中,當Remove時會把狀態自動改爲Deleted
#if ceshi
DbContextTransaction transaction = null;
try
{
using (var context = GetContext)
{
using (transaction = context.Database.BeginTransaction())
{
//if (_module.Set<TEntity>().Any(o => o.Id == entity.Id))
//{
context.Set<TEntity>().Attach(entity);
context.Set<TEntity>().Remove(entity);
int rtnNumber = context.SaveChanges();
transaction.Commit();
return rtnNumber;
//}
//return 0;
}
}
}
catch (Exception error)
{
if (transaction != null)
transaction.Rollback();
throw new Exception(error.Message);
}
#endif
#endregion
GetContext.Configuration.AutoDetectChangesEnabled = false;
DbEntityEntry<TEntity> entry = GetContext.Entry(entity);
GetContext.Configuration.ValidateOnSaveEnabled = false;
entry.State = EntityState.Deleted;
GetContext.Configuration.AutoDetectChangesEnabled = true;
int rtnNumber = GetContext.SaveChanges();
Dispose();
return rtnNumber;
}
/// <summary>
/// 刪除-擴展方法
/// </summary>
/// <param name="predicate"></param>
/// <returns></returns>
public int Delete(Expression<Func<TEntity, bool>> predicate)
{
int rtnNumber = GetContext.Set<TEntity>().Where(predicate).Delete();
Dispose();
return rtnNumber;
}
/// <summary>
/// 刪除多條記錄
/// </summary>
/// <param name="entities"></param>
/// <returns></returns>
public int DeleteRange(IEnumerable<TEntity> entities)
{
try
{
foreach (var entity in entities)
{
var entry = GetContext.Entry(entity);
if (entry.State == EntityState.Detached)
{
entry.State = EntityState.Deleted;
}
}
int rtnNumber = GetContext.SaveChanges();
Dispose();
return rtnNumber;
}
catch (Exception error)
{
throw new Exception(error.Message);
}
}
#endregion
#region 執行語句
public int ExecuteSqlCommand(string sql, object[] paras)
{
DbContextTransaction transaction = null;
try
{
using (transaction = GetContext.Database.BeginTransaction())
{
int rtnNUmber = paras == null
? GetContext.Database.ExecuteSqlCommand(sql)
: GetContext.Database.ExecuteSqlCommand(sql, paras);
GetContext.SaveChanges();
transaction.Commit();
Dispose();
return rtnNUmber;
}
}
catch (Exception error)
{
if (transaction != null)
transaction.Rollback();
throw new Exception("數據執行時發生異常:" + error.Message);
}
}
public List<TEntity> SqlQuery(string queryCmdStr, object[] paras)
{
try
{
var lists= paras == null
? GetContext.Database.SqlQuery<TEntity>(queryCmdStr).ToList()
: GetContext.Database.SqlQuery<TEntity>(queryCmdStr, paras).ToList();
Dispose();
return lists;
}
catch (Exception error)
{
throw new Exception(error.Message);
}
}
#endregion
}