/Prototypes/AomDB/NAomDAL/DAL/EntityRepository.cs
C# | 244 lines | 166 code | 47 blank | 31 comment | 2 complexity | d5731cd7528fb3cbe75d713b00c06cae MD5 | raw file
- #region Copyright
- //
- // Copyright (C) 2008 VirtualStaticVoid <virtualstaticvoid@gmail.com>
- //
- // 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/>.
- //
- #endregion
-
- using System;
- using System.Data.Linq;
- using System.Data.Linq.Mapping;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Xml.Linq;
- using NAom.Core;
-
- namespace NAom.DAL
- {
- public class EntityRepository<TEntity> : IRepository<TEntity>
- where TEntity : class, IEntity //, new()
- {
-
- private readonly DynamicType<TEntity> _dynamicType;
- private readonly IDynamicTypeFactory<TEntity> _dynamicTypeFactory;
-
- private readonly DataContext _dbCtx;
- private readonly ITable _linq2SQLTable;
-
- public EntityRepository(EntityType entityType)
- {
- EntityType = entityType;
-
- _dynamicType = CreateDynamicType(entityType);
- _dynamicTypeFactory = _dynamicType.CreateFactory();
-
- #region Goo
-
- // since Type.GetType(string) != _dynamicTypeFactory.GeneratedType for dynamic assemblies,
- // DataContext.GetTable() fails with InvalidOperationException: Could not retrieve a Table for inheritance subtype 'TDynamicType', try Table of TDynamicType instead.
- // hook up TypeResolve, so that the correct type can be returned to
- // the DataContext when it's busy reflecting
- Type generatedType = _dynamicTypeFactory.GeneratedType;
-
- ResolveEventHandler resolveEventHandler = (o, e) =>
- {
- if (String.CompareOrdinal(generatedType.FullName, e.Name) == 0)
- return generatedType.Assembly;
- return null;
- };
-
- AppDomain.CurrentDomain.TypeResolve += resolveEventHandler;
-
- #endregion
-
- _dbCtx = CreateDataContext(entityType, _dynamicTypeFactory.GeneratedType);
- _linq2SQLTable = GetTable(_dynamicTypeFactory.GeneratedType);
-
- #region Goo
-
- // clean up, remove handler
- AppDomain.CurrentDomain.TypeResolve -= resolveEventHandler;
-
- #endregion
-
- #if DEBUG
- _dbCtx.Log = Console.Out;
- #endif
-
- }
-
- public EntityType EntityType { get; private set; }
-
- #region IRepository<TEntity> Members
-
- public TEntity CreateInstance()
- {
- return _dynamicTypeFactory.CreateInstance();
- }
-
- public IQueryable<TEntity> GetAll()
- {
- return new InternalEntityQueryable<TEntity>
- (
- _dynamicTypeFactory.GeneratedType,
- _linq2SQLTable.AsQueryable().OfType<TEntity>()
- );
- }
-
- public IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> expression)
- {
- return GetAll().Where(expression);
- }
-
- public void Add(TEntity entity)
- {
- _linq2SQLTable.InsertOnSubmit(entity);
- _dbCtx.SubmitChanges();
- }
-
- public void Update(TEntity entity)
- {
- _linq2SQLTable.DeleteOnSubmit(entity);
- _dbCtx.SubmitChanges();
- }
-
- public void Delete(TEntity entity)
- {
- _linq2SQLTable.DeleteOnSubmit(entity);
- _dbCtx.SubmitChanges();
- }
-
- public void Delete(Expression<Func<TEntity, bool>> expression)
- {
- foreach (TEntity entity in GetAll().Where(expression))
- {
- _linq2SQLTable.DeleteOnSubmit(entity);
- }
- _dbCtx.SubmitChanges();
- }
-
- #endregion
-
- #region Support
-
- private static DynamicType<TEntity> CreateDynamicType(EntityType entityType)
- {
- Type genericPropertyTypeType = typeof(PropertyType<>);
-
- DynamicType<TEntity> dynamicType = new DynamicType<TEntity>(entityType.Name);
-
- // add required property types
- dynamicType.Properties.AddRange(InterfaceSupport.DerivePropertyTypes(typeof(IEntity)));
-
- // now add user-defined properties
- foreach (IInternalAttributeType attributeType in entityType.AttributeTypes)
- {
- Type propertyTypeType = genericPropertyTypeType.MakeGenericType(attributeType.RealDataType);
- IPropertyType propertyType = (IPropertyType)Activator.CreateInstance(propertyTypeType, new object[] { attributeType.Name });
- dynamicType.Properties.Add(propertyType);
-
- // store for later
- attributeType.PropertyType = propertyType;
- }
-
- return dynamicType;
-
- }
-
- private static DataContext CreateDataContext(EntityType entityType, Type generatedType)
- {
-
- // generate Linq2SQL mapping
- XDocument mappingXmlDoc = CreateXmlMappingSource(entityType, generatedType);
-
- // load it
- XmlMappingSource mappingSource = XmlMappingSource.FromXml(mappingXmlDoc.ToString());
-
- // create the data context using this mapping
- DataContext dbCtx = new DataContext(Properties.Settings.Default.AomDBConnectionString, mappingSource);
-
- return dbCtx;
- }
-
- private ITable GetTable(Type generatedType)
- {
- // get the table for the generated type
- return _dbCtx.GetTable(generatedType);
- }
-
- private static XDocument CreateXmlMappingSource(EntityType entityType, Type generatedType)
- {
- // NOTE:
- // The Name column is set as the primary key, since scope_identity() doesn't work
- // for views which have "instead of" triggers
-
- XElement typeXElement;
- XNamespace xmlns = "http://schemas.microsoft.com/linqtosql/mapping/2007";
- XDocument mappingXmlDoc = new XDocument
- (
- new XElement
- (
- xmlns + "Database",
- new XAttribute("xmlns", xmlns.NamespaceName),
- new XAttribute("Name", "AomDB"),
- new XElement
- (
- xmlns + "Table",
- new XAttribute("Name", entityType.GeneratedViewName),
- typeXElement = new XElement
- (
- xmlns + "Type",
- new XAttribute("Name", generatedType.FullName),
- new XElement
- (
- xmlns + "Column",
- new XAttribute("Name", "Id"),
- new XAttribute("Member", "Id"),
- new XAttribute("Storage", "_dynamicId"),
- new XAttribute("AutoSync", "OnInsert"),
- new XAttribute("IsDbGenerated", true),
- new XAttribute("CanBeNull", false),
- new XAttribute("UpdateCheck", "Never")
- ),
- new XElement(xmlns + "Column", new XAttribute("Name", "Version"), new XAttribute("Member", "Version"), new XAttribute("Storage", "_dynamicVersion"), new XAttribute("AutoSync", "Always"), new XAttribute("IsDbGenerated", true), new XAttribute("IsVersion", true), new XAttribute("CanBeNull", false), new XAttribute("UpdateCheck", "Never")),
- new XElement(xmlns + "Column", new XAttribute("Name", "Name"), new XAttribute("Member", "Name"), new XAttribute("Storage", "_dynamicName"), new XAttribute("IsPrimaryKey", true), new XAttribute("CanBeNull", false), new XAttribute("UpdateCheck", "Never"))
- )
- )
- )
- );
-
- foreach (IInternalAttributeType attributeType in entityType.AttributeTypes)
- {
- typeXElement.Add
- (
- new XElement
- (
- xmlns + "Column",
- new XAttribute("Name", attributeType.Name),
- new XAttribute("Member", attributeType.Name),
- new XAttribute("Storage", "_dynamic" + attributeType.Name),
- new XAttribute("CanBeNull", !attributeType.RealDataType.IsValueType),
- new XAttribute("UpdateCheck", "Never")
- )
- );
- }
-
- return mappingXmlDoc;
- }
-
- #endregion
-
- }
- }