/SFWK.DAO/SFWKEFRepository.cs
C# | 429 lines | 258 code | 51 blank | 120 comment | 59 complexity | b20dfe2ae1086cc79288b7cd22eddef3 MD5 | raw file
- //------------------------------------------------------------------------------
- //SFWK Framework
- //Copyright (C) 2011 SQLI
-
- //This program is free software: you can redistribute it and/or modify
- //it under the terms of the GNU General Public License as published by
- //the Free Software Foundation, either version 3 of the License, or
- //(at your option) any later version.
-
- //This program is distributed in the hope that it will be useful,
- //but WITHOUT ANY WARRANTY; without even the implied warranty of
- //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- //GNU General Public License for more details.
-
- //You should have received a copy of the GNU General Public License
- //along with this program. If not, see <http://www.gnu.org/licenses/>.
- //------------------------------------------------------------------------------
-
- using System;
- using System.Linq;
- using System.Reflection;
-
- using System.Linq.Expressions;
- using System.Data.Linq;
- using System.Data.Linq.Mapping;
-
-
- using SFWK.Core;
- using System.Diagnostics;
- using System.Collections.Generic;
- using System.Data.Objects;
- using System.Data.Objects.DataClasses;
- using System.Data;
- using SFWK.Core.DTO;
- using SFWK.Core.ExpressionBuilder;
- using System.Linq.Dynamic;
- using SFWK.Core.Linq;
-
- namespace SFWK.DAO
- {
- /// <summary>
- /// Unic Access point to DAO objects
- /// Provides generic Submit, Attach, Detach, CRUD and Search methods
- /// Provides DataContext Access
- /// SubmitChanges method must be called to update data in DB!!!
- /// </summary>
- /// <typeparam name="TEntity"></typeparam>
- public class SFWKEFRepository<TDataContext>
- where TDataContext : ObjectContext, new()
- {
- #region Accessors
- /// <summary>
- /// Accessor to data context
- /// </summary>
- public TDataContext DataContext
- {
- get
- {
- return DataContextFactory.GetScopedDataContext<TDataContext>();// EntityFrameworkHelper<TDataContext>.Context;
- }
- }
- #endregion
-
- #region Save
- /// <summary>
- /// Saves an entity (Insert or Update)
- /// </summary>
- /// <typeparam name="TEntity"></typeparam>
- /// <param name="os"></param>
- /// <param name="entity"></param>
- /// <returns></returns>
- public TEntity Save<TEntity>(ObjectSet<TEntity> os, TEntity entity) where TEntity : class, IObjectWithChangeTracker, new()
- {
- TEntity workingEntity = SFWK.Core.EntityHelper.ValidateObject<TEntity>(entity); // For composition stuff, derived object can be passed -> transform derived to base object
- // LogHelper.Log(this, "SaveEntity", SFWK.Core.SerializeHelper.SerializeToXml(entity), ELogSeverity.Debug );
- // LogTracker("", entity);
- // LogObjectStateManager("Before apply Change", os.Context.ObjectStateManager);
- os.ApplyChanges<TEntity>(workingEntity);
- // LogObjectStateManager("After apply Change", os.Context.ObjectStateManager);
-
- os.Context.SaveChanges();
- // LogObjectStateManager("After SAVE CHANGES", os.Context.ObjectStateManager);
-
- if (!entity.GetType().Equals(typeof(TEntity)))
- SFWK.Core.EntityHelper.CopyObjectValues<TEntity>(workingEntity, entity); // For composition stuff, derived object can be passed -> transform base to derived object
- //entity.AcceptChanges();
-
- // IMPORTANT we must accept change on all entities commited to the db before returning result.
- AcceptChangesOnAllEntities<TEntity>(os);
- return entity;
- }
- #endregion
-
- #region Delete
- /// <summary>
- /// Delete an Entity
- /// </summary>
- /// <typeparam name="TEntity"></typeparam>
- /// <param name="os"></param>
- /// <param name="entity"></param>
- public void Delete<TEntity>(ObjectSet<TEntity> os, TEntity entity) where TEntity : class, IObjectWithChangeTracker, new()
- {
- entity = SFWK.Core.EntityHelper.ValidateObject<TEntity>(entity);// For composition stuff, derived object can be passed -> transform derived to base object
- os.ApplyChanges<TEntity>(entity);
- os.Context.DeleteObject(entity);
- os.Context.SaveChanges();
- entity.AcceptChanges();
- // AcceptChangesOnAllEntities<TEntity>(os);
- }
- #endregion
-
- private void LogObjectStateManager(String title, ObjectStateManager osm)
- {
- LogHelper.Log(osm, "DUMP STATE", title, ELogSeverity.Error);
- foreach(var x in osm.GetObjectStateEntries( EntityState.Added )) {
- if (x.Entity != null) LogHelper.Log(osm, "Added", SerializeHelper.SerializeXml( x.EntityKey) , ELogSeverity.Error);
- else LogHelper.Log(osm, "Added", x.EntitySet + "-" + x.EntityKey , ELogSeverity.Error);
- }
- foreach(var x in osm.GetObjectStateEntries( EntityState.Deleted )) {
- if (x.Entity != null) LogHelper.Log(osm, "Deleted", SerializeHelper.SerializeXml(x.EntityKey), ELogSeverity.Error);
- else LogHelper.Log(osm, "Deleted", x.EntitySet + "-" + x.EntityKey, ELogSeverity.Error);
- }
- foreach(var x in osm.GetObjectStateEntries( EntityState.Modified )) {
- if (x.Entity != null) LogHelper.Log(osm, "Modified", SerializeHelper.SerializeXml(x.EntityKey), ELogSeverity.Error);
- else LogHelper.Log(osm, "Modified", x.EntitySet + "-" + x.EntityKey, ELogSeverity.Error);
- }
- foreach (var x in osm.GetObjectStateEntries(EntityState.Unchanged))
- {
- if (x.Entity != null) LogHelper.Log(osm, "Unchanged", SerializeHelper.SerializeXml(x.EntityKey), ELogSeverity.Error);
- else LogHelper.Log(osm, "Unchanged", x.EntitySet + "-" + x.EntityKey, ELogSeverity.Error);
- }
- }
- private void LogTracker(string tab, IObjectWithChangeTracker ioc)
- {
- LogHelper.Log(ioc, "Traker",tab+ ioc.ChangeTracker.State.ToString()+ ":" + ioc.ToString(), ELogSeverity.Error);
- foreach (var x in ioc.ChangeTracker.ObjectsAddedToCollectionProperties)
- {
- foreach( var y in x.Value) {
- IObjectWithChangeTracker z = y as IObjectWithChangeTracker;
- if (z != null) LogTracker(tab + " ADDED " + x.Key + " ", z);
- }
-
- }
- foreach (var x in ioc.ChangeTracker.ObjectsRemovedFromCollectionProperties)
- {
- foreach (var y in x.Value)
- {
- IObjectWithChangeTracker z = y as IObjectWithChangeTracker;
- if (z != null) LogTracker(tab + " DELET " + x.Key + " ", z);
- }
-
- }
- foreach (var x in ioc.ChangeTracker.OriginalValues)
- {
- LogHelper.Log(ioc, "Traker", tab + x.Key + "=" + x.Value.ToString(), ELogSeverity.Error);
- }
-
- }
-
-
- private static void AcceptChangesOnAllEntities<TEntity>(ObjectSet<TEntity> os) where TEntity : class, IObjectWithChangeTracker, new()
- {
- foreach (var entry in os.Context.ObjectStateManager.GetObjectStateEntries(EntityState.Unchanged))
- {
- IObjectWithChangeTracker ioc = entry.Entity as IObjectWithChangeTracker;
- if (ioc != null) ioc.AcceptChanges();
- }
- }
-
- #region Query builder methods
- /// <summary>
- /// Adds Where Clause to ObjectQuery from string filter
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="objectQuery"></param>
- /// <param name="filter"></param>
- /// <returns></returns>
- //protected IQueryable<T> setWhereClause<T>(IQueryable<T> queryable, string filter) where T : class
- //{
- // return queryable.Where(!string.IsNullOrEmpty(filter) ? ExpressionSerializerHelper<T>.Deserialize(CompressionHelper.Decompress(filter)) : x => true);
- //}
-
- /// <summary>
- /// Adds Order by Clause to ObjectQuery from string filter
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="queryable"></param>
- /// <param name="orderBy"></param>
- /// <param name="defaultOrderBy"></param>
- /// <returns></returns>
- //protected IQueryable<T> setOrderByClause<T>(IQueryable<T> queryable, string orderBy, Expression<Func<T, object>> defaultOrderBy) where T : class
- //{
- // return queryable.OrderBy(!string.IsNullOrEmpty(orderBy) ? ExpressionSerializerHelper<T>.DeserializeOrderBy(orderBy) : defaultOrderBy);
- //}
-
- /// <summary>
- /// Adds Include graph to query
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="objectQuery"></param>
- /// <param name="graphs"></param>
- /// <returns></returns>
- protected ObjectQuery<T> setInclude<T>(ObjectQuery<T> objectQuery, ControlledGraph<T> graph)
- {
- if (graph.Graph != null && graph.Graph.Count > 0)
- foreach (string val in graph.Graph)
- if (val != null)
- objectQuery = objectQuery.Include(val);
- return objectQuery;
- }
-
- /// <summary>
- /// Build query with include graph, where clause, and orderby clause
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="objectQuery"></param>
- /// <param name="graphs"></param>
- /// <param name="filter"></param>
- /// <param name="orderBy"></param>
- /// <param name="defaultOrderBy"></param>
- /// <returns></returns>
- protected IQueryable<T> BuildQuery<T>(ControlledGraph<T> graph, string filter, string orderBy)
- where T : class
- {
- IQueryable<T> res = setInclude<T>(this.DataContext.CreateObjectSet<T>(typeof(T).Name), graph).Where(!string.IsNullOrEmpty(filter) ? ExpressionSerializerHelper<T>.Deserialize(CompressionHelper.Decompress(filter)) : x => true);
- if (!string.IsNullOrEmpty(orderBy))
- {
- Expression<Func<IQueryable<T>, IOrderedQueryable>> ex = ExpressionSerializerHelper<T>.DeserializeOrderBy(orderBy);
- if (ex != null)
- res = ex.Compile().Invoke(res) as IQueryable<T>;
- }
- return res;
- }
- protected IQueryable<T> BuildQuery<T>(ControlledGraph<T> graph, string filter, Expression<Func<IQueryable<T>, IOrderedQueryable>> orderBy)
- where T : class
- {
- IQueryable<T> res = setInclude<T>(this.DataContext.CreateObjectSet<T>(typeof(T).Name), graph).Where(!string.IsNullOrEmpty(filter) ? ExpressionSerializerHelper<T>.Deserialize(CompressionHelper.Decompress(filter)) : x => true);
- if (orderBy != null)
- {
- res = orderBy.Compile().Invoke(res) as IQueryable<T>;
- }
- return res;
- }
-
-
-
- protected IQueryable<T> BuildQuery<T>(string filter, string orderBy)
- where T : class
- {
- return BuildQuery<T>(null, filter, orderBy);
- }
- protected IQueryable<T> BuildQuery<T>(string filter, Expression<Func<IQueryable<T>, IOrderedQueryable>> orderBy)
- where T : class
- {
- return BuildQuery<T>(null, filter, orderBy);
- }
-
- #endregion
-
- #region SearchGraph
- /// <summary>
- /// Search for a list of Entities, and retrieve them with the requested linked object's graph list
- /// </summary>
- /// <typeparam name="T">Type of searched entities</typeparam>
- /// <param name="filter">serialized Where clause lambda expression</param>
- /// <param name="from">Paging: start index</param>
- /// <param name="range">Paging: number of record to get</param>
- /// <param name="orderBy">serialized Sort lambda expresion</param>
- /// <param name="graphs">List of linked object graphs to be retrieved</param>
- /// <param name="defaultOrderBy">If order by null, set a default order by</param>
- /// <returns>List of found records with the number of record available</returns>
- public SearchResultList<T> SearchGraph<T>(string filter, int? from, int? range, string orderBy, ControlledGraph<T> graph)
- where T : class
- {
- IQueryable<T> result = BuildQuery<T>(graph, filter, orderBy);
- int count = result.Count();
- if (from != null) result = result.Skip((int)from);
- if (range != null) result = result.Take((int)range);
- return new SearchResultList<T>(result.ToList(), count);
- }
- public SearchResultList<T> SearchGraph<T>(string filter, int? from, int? range, Expression<Func<IQueryable<T>, IOrderedQueryable>> orderBy, ControlledGraph<T> graph)
- where T : class
- {
- IQueryable<T> result = BuildQuery<T>(graph, filter, orderBy);
- int count = result.Count();
- if (from != null) result = result.Skip((int)from);
- if (range != null) result = result.Take((int)range);
- return new SearchResultList<T>(result.ToList(), count);
- }
-
- public SearchResultList<T> SearchGraph<T>(ControlledGraph<T> graph, Expression<Func<T, bool>> filter)
- where T : class
- {
- IQueryable<T> result = setInclude<T>(this.DataContext.CreateObjectSet<T>(typeof(T).Name), graph).Where(filter);
- int count = result.Count();
- return new SearchResultList<T>(result.ToList(), count);
- }
- #endregion SearchGraph
-
- #region Search
- /// <summary>
- /// Search for a list of Entities
- /// </summary>
- /// <typeparam name="T">Type of searched entities</typeparam>
- /// <param name="filter">serialized Where clause lambda expression</param>
- /// <param name="from">Paging: start index</param>
- /// <param name="range">Paging: number of record to get</param>
- /// <param name="orderBy">serialized Sort lambda expresion</param>
- /// <param name="defaultOrderBy">If order by null, set a default order by</param>
- /// <returns>List of found records with the number of record available</returns>
- private SearchResultList<T> _search<T>(string filter, int? from, int? range, object orderBy)
- where T : class
- {
- IQueryable<T> result = null;
- if (!string.IsNullOrEmpty(filter))
- result = this.DataContext.CreateObjectSet<T>(typeof(T).Name).Where(ExpressionSerializerHelper<T>.Deserialize(CompressionHelper.Decompress(filter)));
- else
- result = this.DataContext.CreateObjectSet<T>(typeof(T).Name);
-
- if (orderBy != null)
- {
- if (orderBy is string && orderBy != string.Empty)
- {
- Expression<Func<IQueryable<T>, IOrderedQueryable>> ex = ExpressionSerializerHelper<T>.DeserializeOrderBy((string)orderBy);
- if (ex != null)
- result = ex.Compile().Invoke(result) as IQueryable<T>;
- }
- else if (orderBy is Expression<Func<IQueryable<T>, IOrderedQueryable>>)
- {
- result = ((Expression<Func<IQueryable<T>, IOrderedQueryable>>)orderBy).Compile().Invoke(result) as IQueryable<T>;
- }
- }
-
- // - 03.09.2010 - Only compute count if FROM value equals 0
- int? count = null;
-
- if (from.HasValue && from.Value == 0)
- {
- count = result.Count();
- }
-
- if (from != null) result = result.Skip((int)from);
- if (range != null) result = result.Take((int)range);
- var res = result.ToList();
-
- if (!from.HasValue && !range.HasValue)
- {
- count = res.Count;
- }
-
- return new SearchResultList<T>(res, count);
- //
- }
-
- public SearchResultList<T> Search<T>(string filter, int? from, int? range, string orderBy)
- where T : class
- { return _search<T>( filter, from, range, orderBy);}
-
- public SearchResultList<T> Search<T>(string filter, int? from, int? range, Expression<Func<IQueryable<T>, IOrderedQueryable>> orderBy)
- where T : class
- { return _search<T>(filter, from, range, orderBy); }
-
-
-
-
- public SearchResultList<T> Search<T>(string filter)
- where T : class
- {
- IQueryable<T> result = this.DataContext.CreateObjectSet<T>(typeof(T).Name).Where(ExpressionSerializerHelper<T>.Deserialize(CompressionHelper.Decompress(filter)));
- // - 03.09.2010 - second database call for count has no utility
- var res = result.ToList();
- return new SearchResultList<T>(res, res.Count);
- //
- }
- public SearchResultList<T> Search<T>(Expression<Func<T, bool>> filter) where T : class
- {
- IQueryable<T> result = null;
- if (filter != null)
- result = this.DataContext.CreateObjectSet<T>(typeof(T).Name).Where(filter);
- else
- result = this.DataContext.CreateObjectSet<T>(typeof(T).Name);
-
- // - 03.09.2010 - second database call has no utility
- var res = result.ToList();
- return new SearchResultList<T>(res, res.Count);
- //
- }
- #endregion Search
-
- #region SearchIds
- public SearchResultList<TResult> SearchIds<T, TResult>(string filter, Expression<Func<T, TResult>> selectClause)
- where T : class
- {
- IQueryable<T> result = null;
- if (!string.IsNullOrEmpty(filter))
- result = this.DataContext.CreateObjectSet<T>(typeof(T).Name).Where(ExpressionSerializerHelper<T>.Deserialize(CompressionHelper.Decompress(filter)));
- else
- result = this.DataContext.CreateObjectSet<T>(typeof(T).Name);
-
- // - 03.09.2010 - Count from database has no utility --> directly count result list
- var res = result.Select(selectClause).ToList();
- return new SearchResultList<TResult>(res, res.Count);
- //
- }
- #endregion
-
- #region Get
-
- /// <summary>
- /// Gets an entity depending on the filter passed
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="filter"></param>
- /// <returns></returns>
- public T GetByClause<T>(Expression<Func<T, bool>> filter) where T : class
- {
- return this.DataContext.CreateObjectSet<T>(typeof(T).Name).Where(filter).FirstOrDefault();
- }
-
- public T GetGraphByClause<T>(Expression<Func<T, bool>> filter, ControlledGraph<T> graph) where T : class
- {
- return setInclude<T>(this.DataContext.CreateObjectSet<T>(typeof(T).Name), graph).Where(filter).FirstOrDefault();
- }
- #endregion
-
-
- }
- }
-