public abstract class Repository<T> : IRepository<T> where T : EntityBase,new() { // }
// public abstract class EntityBase : IEntity { // public abstract int Id { get; set; } public object Clone() { return MemberwiseClone(); } }
// EntityBase [TableName("profile")] public class Profile : EntityBase { // [FieldName("profile_id")] public override int Id { get; } [FieldName("userinfo_id")] public int? UserInfoId { get; set; } [FieldName("role_id")] public int RoleId { get; set; } public string Info { get; set; } }
public class ProfileRepository : Repository<Profile> { // public ProfileRepository() : base("PhotoGallery") { // CRUD } }
<connectionStrings> <add name="PhotoGallery" providerName="System.Data.SqlClient" connectionString="server=PC\SQLEXPRESS; database=db_PhotoGallery"/> </connectionStrings>
public interface IUnitOfWork : IDisposable { void Commit(); }
public static class Session { // private static readonly ThreadLocal<IUnitOfWork> CurrentThreadData = new ThreadLocal<IUnitOfWork>(true); public static IUnitOfWork Current { get { return CurrentThreadData.Value; } private set { CurrentThreadData.Value = value; } } public static IUnitOfWork Create(IUnitOfWork uow) { return Current ?? (Current = uow); } }
var uow = new UnitOfWork(); using (Session.Create(uow)) { var profileRepo = new ProfileRepository(); // uow.Commit(); }
internal struct EntityStruct { // internal Type Key { get; private set; } internal EntityBase Value { get; private set; } internal EntityStruct(Type key, EntityBase value) : this() { Key = key; Value = value; } public override bool Equals(object obj) { if (!(obj is EntityStruct)) { throw new TypeAccessException("EntityStruct"); } return Equals((EntityStruct)obj); } public bool Equals(EntityStruct obj) { if (Value.Id != obj.Value.Id) { return false; } return Key == obj.Key; } public override int GetHashCode() { // , // return (unchecked(25 * Key.GetHashCode()) ^ Value.Id.GetHashCode()) & 0x7FFFFFFF; } }
var uow = new UnitOfWork(); using (Session.Create(uow)) { var profileRepo = new ProfileRepository(); // "" , // "" var profiles = profileRepo.Get(x=>x.Info = " "); // "" foreach (var profile in profiles) { profile.Info = " "; } // uow.Commit(); }
internal interface IObjectTracker { // ICollection<EntityStruct> NewObjects { get; } ICollection<EntityStruct> ChangeObjects { get; } // void RegInsertedNewObjects(object sender, AddObjInfoEventArgs e); void RegCleanObjects(object sender, DirtyObjsInfoEventArgs e); } internal class DefaultObjectTracker : IObjectTracker { // - "" , - "" private readonly Dictionary<EntityStruct, EntityStruct> _dirtyCreanPairs; public ICollection<EntityStruct> NewObjects { get; private set; } public ICollection<EntityStruct> ChangeObjects { get { // return _dirtyCreanPairs.GetChangesObjects(); } } internal DefaultObjectTracker() { NewObjects = new Collection<EntityStruct>(); // boxing/unboxing EqualityComparer _dirtyCreanPairs = new Dictionary<EntityStruct, EntityStruct>(new IdentityMapEqualityComparer()); } public void RegInsertedNewObjects(object sender, AddObjInfoEventArgs e) { NewObjects.Add(e.InsertedObj); } public void RegCleanObjects(object sender, DirtyObjsInfoEventArgs e) { var objs = e.DirtyObjs; foreach (var obj in objs) { if (!_dirtyCreanPairs.ContainsKey(obj)) { // "" MemberwiseClone() var cloneObj = new EntityStruct(obj.Key, (EntityBase)obj.Value.Clone()); _dirtyCreanPairs.Add(obj, cloneObj); } } } }
public static ICollection<EntityStruct> GetChangesObjects ( this Dictionary<EntityStruct, EntityStruct> dirtyCleanPairs ) { var result = new List<EntityStruct>(); foreach (var cleanObj in dirtyCleanPairs.Keys) { if (!(cleanObj.Key == dirtyCleanPairs[cleanObj].Key)) { throw new Exception("incorrect types"); } if (ChangeDirtyObjs(cleanObj.Value, dirtyCleanPairs[cleanObj].Value, cleanObj.Key)) { result.Add(cleanObj); } } return result; } public static bool ChangeDirtyObjs(EntityBase cleanObj, EntityBase dirtyObj, Type type) { var props = type.GetProperties(); // foreach (var prop in props) { var cleanValue = prop.GetValue(cleanObj, null); var dirtyValue = prop.GetValue(dirtyObj, null); // , if (!cleanValue.Equals(dirtyValue)) { return true; } } return false; }
internal interface IDetector { // - , - Dictionary<string, IObjectTracker> ObjectDetector { get; } } public sealed class UnitOfWork : IUnitOfWork, IDetector { private readonly Dictionary<string, IObjectTracker> _objectDetector; Dictionary<string, IObjectTracker> IDetector.ObjectDetector { get { return _objectDetector; } } public UnitOfWork() { _objectDetector = new Dictionary<string, IObjectTracker>(); foreach (ConnectionStringSettings conName in ConfigurationManager.ConnectionStrings) { // _objectDetector.Add(conName.Name, new DefaultObjectTracker()); } } }
public static class Session { private static readonly ThreadLocal<IUnitOfWork> CurrentThreadData = new ThreadLocal<IUnitOfWork>(true); public static IUnitOfWork Current { get { return CurrentThreadData.Value; } private set { CurrentThreadData.Value = value; } } public static IUnitOfWork Create(IUnitOfWork uow) { return Current ?? (Current = uow); } // // internal static IObjectTracker GetObjectTracker(string connectionName) { var uow = Current; if (uow == null) { throw new ApplicationException(" Create unit of work context and using Session."); } var detector = uow as IDetector; if (detector == null) { throw new ApplicationException("Create unit of work context and using Session."); } return detector.ObjectDetector[connectionName]; } } }
internal interface IDataSourceProvider : IDisposable { State State { get; } // , void Commit(ICollection<EntityStruct> updObjs); ICollection<T> GetByFields<T>(BinaryExpression exp) where T : EntityBase, new(); } internal class DbProvider : IDataSourceProvider { private IDbConnection _connection; internal DbProvider(IDbConnection connection) { _connection = connection; State = State.Open; } public State State { get; private set; } public ICollection<T> GetByFields<T>(BinaryExpression exp) where T : EntityBase, new() { // select- exp Func<IDbCommand, BinaryExpression, string> cmdBuilder = SelectCommandBulder.Create<T>; ICollection<T> result; using (var conn = _connection) { using (var command = conn.CreateCommand()) { command.CommandText = cmdBuilder.Invoke(command, exp); command.CommandType = CommandType.Text; conn.Open(); result = command.ExecuteListReader<T>(); } } State = State.Close; return result; } public void Commit(ICollection<EntityStruct> updObjs) { if (updObjs.Count == 0) { return; } // - update- exp // - var cmdBuilder = new Dictionary<Func<IDbCommand, ICollection<EntityStruct>, string>, ICollection<EntityStruct>>(); cmdBuilder.Add(UpdateCommandBuilder.Create, updObjs); ExecuteNonQuery(cmdBuilder, packUpdDict, packDeleteDict); } private void ExecuteNonQuery(Dictionary<Func<IDbCommand, ICollection<EntityStruct>, string>, ICollection<EntityStruct>> cmdBuilder) { using (var conn = _connection) { using (var command = conn.CreateCommand()) { var cmdTxtBuilder = new StringBuilder(); foreach (var builder in cmdBuilder) { cmdTxtBuilder.Append(builder.Key.Invoke(command, builder.Value)); } command.CommandText = cmdTxtBuilder.ToString(); command.CommandType = CommandType.Text; conn.Open(); if (command.ExecuteNonQuery() < 1) throw new ExecuteQueryException(command); } } State = State.Close; } private ICollection<T> ExecuteListReader<T>(EntityStruct objs) where T : EntityBase, IEntity, new() { Func<IDbCommand, EntityStruct, string> cmdBuilder = SelectCommandBulder.Create; ICollection<T> result; using (var conn = _connection) { using (var command = conn.CreateCommand()) { command.CommandText = cmdBuilder.Invoke(command, objs); command.CommandType = CommandType.Text; conn.Open(); result = command.ExecuteListReader<T>(); } } State = State.Close; return result; } private void Dispose() { if (State == State.Open) { _connection.Close(); State = State.Close; } _connection = null; GC.SuppressFinalize(this); } void IDisposable.Dispose() { Dispose(); } ~DbProvider() { Dispose(); } }
class DataSourceProviderFactory { static DbConnection CreateDbConnection(string connectionString, string providerName) { if (string.IsNullOrWhiteSpace(connectionString)) { throw new ArgumentException("connectionString is null or whitespace"); } DbConnection connection; DbProviderFactory factory; try { factory = DbProviderFactories.GetFactory(providerName); connection = factory.CreateConnection(); if (connection != null) connection.ConnectionString = connectionString; } catch (ArgumentException) { try { factory = DbProviderFactories.GetFactory("System.Data.SqlClient"); connection = factory.CreateConnection(); if (connection != null) { connection.ConnectionString = connectionString; } } catch (Exception) { throw new Exception("DB connection has been failed."); } } return connection; } public static IDataSourceProvider Create(string connectionString) { var settings = ConfigurationManager.ConnectionStrings[connectionString]; var dbConn = CreateDbConnection(settings.ConnectionString, settings.ProviderName); return new DbProvider(dbConn); } public static IDataSourceProvider CreateByDefaultDataProvider(string connectionString) { var dbConn = CreateDbConnection(connectionString, string.Empty); return new DbProvider(dbConn); } }
internal class TrackerProvider : IDataSourceProvider { private event EventHandler<DirtyObjsInfoEventArgs> DirtyObjEvent; private event EventHandler<UpdateObjsInfoEventArgs> UpdateObjEvent; private readonly IDataSourceProvider _dataSourceProvider; private readonly string _connectionName; private readonly object _syncObj = new object(); private IObjectTracker ObjectTracker { get { lock (_syncObj) { // return Session.GetObjectTracker(_connectionName); } } } public TrackerProvider(string connectionName) { _connectionName = connectionName; _dataSourceProvider = DataSourceProviderFactory.Create(_connectionName); // RegisterEvents(); } public State State { get { return _dataSourceProvider.State; } } private void RegisterEvents() { // if (Session.Current == null) { throw new ApplicationException("Session has should be used. Create a session."); }; // DirtyObjEvent += ObjectTracker.RegCleanObjects; UpdateObjEvent += ObjectTracker.RegUpdatedObjects; } public ICollection<T> GetByFields<T>(BinaryExpression exp) where T : EntityBase, IEntity, new() { // DbProvider var result = _dataSourceProvider.GetByFields<T>(exp); var registratedObjs = result.Select(r => new EntityStruct(typeof(T), r)).ToList(); // "" var handler = DirtyObjEvent; if (handler == null) return result; handler(this, new DirtyObjsInfoEventArgs(registratedObjs)); return result; } public void Commit(ICollection<EntityStruct> updObjs) { // DbProvider _dataSourceProvider.Commit(updObjs, delObjs, addObjs, packUpdObjs, deleteUpdObjs); } public void Dispose() { _dataSourceProvider.Dispose(); } }
public abstract class Repository<T> : IRepository<T> where T : EntityBase, IEntity, new() { private readonly object _syncObj = new object(); private IDataSourceProvider _dataSourceProvider; //c "" private IDataSourceProvider DataSourceProvider { get { lock (_syncObj) { if (_dataSourceProvider.State == State.Close) { _dataSourceProvider = GetDataSourceProvider(); } return _dataSourceProvider; } } } private readonly string _connectionName; protected Repository(string connectionName) { if (string.IsNullOrWhiteSpace(connectionName)) { throw new ArgumentNullException("connectionName"); } _connectionName = connectionName; var dataSourceProvider = GetDataSourceProvider(); if (dataSourceProvider == null) { throw new ArgumentNullException("dataSourceProvider"); } _dataSourceProvider = dataSourceProvider; } private IDataSourceProvider GetDataSourceProvider() { // DbProvider' // //// - TrackerProvider return Session.Current == null ? DataSourceProviderFactory.Create(_connectionName) : new TrackerProvider(_connectionName); } public ICollection<T> Get(Expression<Func<T, bool>> exp) { return DataSourceProvider.GetByFields<T>(exp.Body as BinaryExpression); } } public sealed class UnitOfWork : IUnitOfWork, IDetector { private readonly Dictionary<string, IObjectTracker> _objectDetector; Dictionary<string, IObjectTracker> IDetector.ObjectDetector { get { return _objectDetector; } } public UnitOfWork() { _objectDetector = new Dictionary<string, IObjectTracker>(); foreach (ConnectionStringSettings conName in ConfigurationManager.ConnectionStrings) { _objectDetector.Add(conName.Name, new DefaultObjectTracker()); } } public void Commit() { SaveChanges(); } private void SaveChanges() { foreach (var objectDetector in _objectDetector) { // var provider = new TrackerProvider(objectDetector.Key); provider.Commit( objectDetector.Value.ChangeObjects, objectDetector.Value.DeletedObjects, objectDetector.Value.NewObjects, objectDetector.Value.UpdatedObjects, objectDetector.Value.DeletedWhereExp); } } }
Source: https://habr.com/ru/post/317860/
All Articles