PageRenderTime 21ms CodeModel.GetById 2ms app.highlight 15ms RepoModel.GetById 1ms app.codeStats 0ms

/src/Framework/CoolCode.Data.Xml/Repository.cs

https://bitbucket.org/coolcode/ibs
C# | 337 lines | 215 code | 52 blank | 70 comment | 11 complexity | fbe6a3668ed0b4c6db201461355a77ec MD5 | raw file
  1using System;
  2using System.Collections.Generic;
  3using System.Linq;
  4using System.Text;
  5using System.Data.Linq;
  6using System.Xml.Linq;
  7using System.Reflection;
  8using System.Linq.Expressions;
  9using CoolCode.Reflection;
 10using CoolCode.Caching;
 11using CoolCode.Linq;
 12
 13namespace CoolCode.Data.Xml
 14{
 15    public class Repository<T> : IRepository<T>, IXmlTable, IQueryable<T>, IEnumerable<T>, IDisposable where T : class
 16    {
 17        private static readonly string entityName = typeof(T).Name;
 18        private static ICacheStrategy typeCache;
 19        private static Func<XElement, T, bool> _condition;
 20        private static Func<T, XElement> _entityToXElement;
 21        private static bool _initial = false;
 22        private IDataContext context;
 23        private XmlQueryable<T> table;
 24
 25        public XElement Root { get; set; }
 26        public bool IsChanged { get; set; }
 27        public string ClassName { get; set; }
 28
 29        internal Repository(IDataContext context)
 30        {
 31            this.context = context;
 32            this.table = new XmlQueryable<T>((IQueryExecutor)context);
 33            Initialize();
 34        }
 35
 36        private void Initialize()
 37        {
 38            if (!_initial)
 39            {
 40                typeCache = new HashCacheStrategy();
 41                ExpressionBuilder exprBuilder = new ExpressionBuilder();
 42                _condition = exprBuilder.PrimaryKey<T>().Compile();
 43                _entityToXElement = exprBuilder.ToXElementExpression<T>().Compile();
 44                _initial = true;
 45            }
 46        }
 47
 48        //private XmlQueryable<T> _table = null;
 49
 50        //private XmlQueryable<T> table
 51        //{
 52        //    get
 53        //    {
 54        //        if (_table == null)
 55        //            _table = new XmlQueryable<T>((IQueryExecutor)context);
 56        //        return _table;
 57        //    }
 58        //}
 59
 60        #region IRepository<T> Members
 61
 62        public virtual void Insert(T entity)
 63        {
 64            var xe = _entityToXElement(entity); //XmlConvert.Entity2Xml<T>(entity);
 65            Root.Add(xe);
 66            IsChanged = true;
 67        }
 68
 69        public virtual void Insert(IEnumerable<T> list)
 70        {
 71            foreach (T entity in list)
 72            {
 73                var xe = XmlConvert.Entity2Xml<T>(entity);
 74                Root.Add(xe);
 75            }
 76            IsChanged = true;
 77        }
 78
 79        public virtual void Update(T entity)
 80        {
 81            Delete(entity);
 82            Insert(entity);
 83            //SaveByPrimaryKeys(entity);
 84            IsChanged = true;
 85        }
 86
 87        //public virtual void Update(T entity, T original)
 88        //{
 89        //    db.Attach(entity, original);
 90        //}
 91
 92        public virtual void Update(IEnumerable<T> list)
 93        {
 94            foreach (T entity in list)
 95            {
 96                var xe = XmlConvert.Entity2Xml<T>(entity);
 97                Root.Add(xe);
 98            }
 99            IsChanged = true;
100        }
101
102        public virtual void Delete(T entity)
103        {
104            DeleteByPrimaryKeys(entity);
105            IsChanged = true;
106        }
107
108        public virtual void Delete(IQueryable<T> query)
109        {
110            Delete(query.ToList());
111        }
112
113        public virtual void Delete(IEnumerable<T> list)
114        {
115            //Get PrimaryKeys
116            string[] primaryKeys = typeCache.GetItem<T>("ColumnAttribute") as string[];
117            if (primaryKeys == null)
118            {
119                primaryKeys = BLReflection.GetPropFrom<System.Data.Linq.Mapping.ColumnAttribute, T>(c => c.IsPrimaryKey);
120                typeCache.AddItem<T>(primaryKeys, "ColumnAttribute");
121            }
122            int len = primaryKeys.Length;
123            string[] pkValue = new string[len];
124
125            //Initial Expression
126            // instance  
127            ParameterExpression s = Expression.Parameter(typeof(XElement), "s");
128            // method                           
129            var m = typeof(XElement).GetMethod("Element", new Type[] { typeof(XName) });
130            Expression cond = Expression.Constant(false);
131            // Expression condTrue  = Expression.Constant(true );
132            MemberExpression[] props = new MemberExpression[len];
133
134            for (int i = 0; i < len; i++)
135            {
136                var mcall = Expression.Call(s, m,
137                        new Expression[] { Expression.Constant((XName)primaryKeys[i], typeof(XName)) }             // arguments  
138                       );
139                props[i] = Expression.Property(mcall, "Value");
140            }
141
142            //Join Expression
143            foreach (var entity in list)
144            {
145                Expression subcond = null;
146                for (int i = 0; i < len; i++)
147                {
148                    //Method 1: Get Property and cache it for reuse
149                    var p = typeCache.GetItem<T>("Property" + primaryKeys[i]) as PropertyInfo;
150                    if (p == null)
151                    {
152                        Type t = typeof(T);
153                        p = t.GetProperty(primaryKeys[i]);
154                        typeCache.AddItem<T>(p, "Property" + primaryKeys[i]);
155                    }
156                    pkValue[i] = XmlConvert.SerializeObject(p.GetValue(entity, null));
157
158                    //Method 2: Get Property directly every time 
159                    // pkValue[i] = XmlConvert.SerializeObject(BLReflection.GetPropValue(TEntity, primaryKeys[i]));
160
161                    //Join Condition
162                    var value = Expression.Constant(pkValue[i], typeof(string));
163                    if (i == 0)
164                        subcond = BinaryExpression.Equal(props[i], value);
165                    else
166                        subcond = BinaryExpression.AndAlso(subcond, BinaryExpression.Equal(props[i], value));
167                }
168                cond = BinaryExpression.OrElse(cond, subcond);
169            }
170
171            // lambda
172            var lambda = Expression.Lambda<Func<XElement, bool>>(cond, new ParameterExpression[] { s });
173
174            var xe = Root.Descendants(ClassName).Where(lambda.Compile());
175            xe.Remove();
176
177            IsChanged = true;
178        }
179
180        public virtual void Delete(Expression<Func<T, bool>> predicate)
181        {
182            var query = XmlContext.Query<T>(predicate, this.context);
183            query.Remove();
184            IsChanged = true;
185        }
186
187        public virtual IQueryable<T> In<P>(Expression<Func<T, P>> property, params P[] values)
188        {
189            throw new NotImplementedException();
190        }
191
192        public virtual IQueryable<T> Query()
193        {
194            //return table;
195            throw new NotImplementedException();
196        }
197
198        public virtual IQueryable<T> Query(Expression<Func<T, bool>> predicate)
199        {
200            //return table.Where(predicate);
201            throw new NotImplementedException();
202        }
203
204        //IQueryable<T> IRepository<T>.Where(Expression<Func<T, bool>> predicate)
205        //{
206        //    //return table.Where(predicate);
207        //    throw new NotImplementedException();
208        //}
209
210        public virtual T Get(Expression<Func<T, bool>> predicate)
211        {
212            //return table.FirstOrDefault(predicate); 
213            throw new NotImplementedException();
214        }
215
216
217        #endregion
218
219        #region IEnumerable<T> Members
220
221        public IEnumerator<T> GetEnumerator()
222        {
223            return ((IEnumerable<T>)table).GetEnumerator();
224        }
225
226        #endregion
227
228        #region IEnumerable Members
229
230        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
231        {
232            return this.GetEnumerator();
233        }
234
235        #endregion
236
237        #region IQueryable Members
238
239        Type IQueryable.ElementType
240        {
241            get
242            {
243                return typeof(T);
244            }
245        }
246
247        Expression IQueryable.Expression
248        {
249            get
250            {
251                return ((IQueryable)table).Expression; // return Expression.Constant(table);
252            }
253        }
254
255        IQueryProvider IQueryable.Provider
256        {
257            get { return ((IQueryable)table).Provider; }
258        }
259
260        #endregion
261
262        #region IDisposable Members
263
264        public virtual void Dispose()
265        {
266            if (context != null)
267            {
268                context.Dispose();
269            }
270        }
271
272        #endregion
273
274        #region private methods
275
276        private void DeleteByPrimaryKeys(T entity)
277        {
278            var cond = getConditionDelegate(entity);
279            var xe = Root.Descendants(ClassName).Where(cond);
280            xe.Remove();
281        }
282
283        private void SaveByPrimaryKeys(T entity)
284        {
285            DeleteByPrimaryKeys(entity);
286            var xe = _entityToXElement(entity); //XmlConvert.Entity2Xml<T>(TEntity);
287            Root.Add(xe);
288        }
289
290        private Func<XElement, bool> getConditionDelegate(T entity)
291        {
292            return (XElement x) => _condition(x, entity);
293        }
294
295        #region Old Methods
296        /*
297        private Func<XElement, bool> PrimaryKeyExpression(T TEntity)
298        {
299            string[] primaryKeys = typeCache.GetItem<T>("ColumnAttribute") as string[];
300            if (primaryKeys == null)
301            {
302                primaryKeys = BLReflection.GetPropFrom<System.Data.Linq.Mapping.ColumnAttribute, T>(c => c.IsPrimaryKey);
303                typeCache.AddItem<T>(primaryKeys, "ColumnAttribute");
304            }
305            return PrimaryKeyExpression(TEntity, primaryKeys);
306        }
307
308        private Func<XElement, bool> PrimaryKeyExpression(T TEntity, string[] primaryKeys)
309        {
310            string[] pkValue = new string[primaryKeys.Length];
311
312            for (int i = 0; i < primaryKeys.Length; i++)
313            {
314                //Method 1: Get Property and cache it for reuse
315                var p = typeCache.GetItem<T>("Property" + primaryKeys[i]) as PropertyInfo;
316                if (p == null)
317                {
318                    Type t = typeof(T);
319                    p = t.GetProperty(primaryKeys[i]);
320                    typeCache.AddItem<T>(p, "Property" + primaryKeys[i]);
321                }
322                pkValue[i] = XmlConvert.SerializeObject(p.GetValue(TEntity, null));
323            }
324
325            ExpressionBuilder builder = new ExpressionBuilder();
326            var condExpr = builder.Where(primaryKeys, pkValue);
327            var cond = condExpr.Compile();
328
329            return cond;
330        }
331        */
332        #endregion
333
334        #endregion
335
336    }
337}