首页 > 代码库 > NHibernate动态添加表
NHibernate动态添加表
NHibernate动态添加表
设置和动态扩展表差不多,添加了一个模板hbm.xml文件,用于创建动态hbm.xml,HibernateUtil无改动。
MappingManger添加了两个方法
1 public static void UpdateClassMapping(DynamicTestModel dynamicModel) 2 { 3 var session = HibernateUtil.Instance.CurrentSession; 4 var fileName = "hbm_template/Template.hbm.xml"; 5 var file = File.ReadAllText(fileName); 6 file = file.Replace("@assembly", dynamicModel.GetType().Assembly.GetName().Name) 7 .Replace("@namespace", dynamicModel.GetType().Namespace) 8 .Replace("@class", dynamicModel.EntityName) 9 .Replace("@table", "Dynamic_" + dynamicModel.EntityName);10 11 var xDocument = new XmlDocument();12 xDocument.LoadXml(file);13 14 var dynamicElements = xDocument.DocumentElement.GetElementsByTagName("dynamic-component");15 XmlElement dynamicElement = null;16 if (dynamicElements.Count > 0)17 {18 dynamicElements[0].InnerXml = string.Empty;19 dynamicElement = dynamicElements[0] as XmlElement;20 }21 22 foreach (DictionaryEntry property in dynamicModel.CustomProperties)23 {24 var newElement = CreatePropertyElement(xDocument, dynamicElement.NamespaceURI, property);25 dynamicElement.AppendChild(newElement);26 }27 28 Console.WriteLine(xDocument.OuterXml);29 xDocument.Save("hbm/" + dynamicModel.EntityName + ".hbm.xml");30 }31 32 private static XmlElement CreatePropertyElement(XmlDocument document, string parentNamespace, DictionaryEntry property)33 {34 var element = document.CreateElement("property", parentNamespace);35 36 element.SetAttribute("name", property.Key as string);37 element.SetAttribute("column", property.Key as string);38 element.SetAttribute("type", property.Value.GetType().Name);39 element.SetAttribute("not-null", "false");40 return element;41 }
CustomizableEntity类添加了一个属性
public string auto_id { get; set; }
创建类DynamicTestModel
1 namespace DynamicTableTest.DynamicTable 2 { 3 public class DynamicTestModel : CustomizableEntity 4 { 5 public string EntityName { get; set; } 6 7 8 public DynamicTestModel(string entityName) 9 {10 // TODO: Complete member initialization11 this.EntityName = entityName;12 }13 }14 }
添加DynamicEntityTuplizer
1 using NHibernate; 2 using NHibernate.Mapping; 3 using NHibernate.Properties; 4 using NHibernate.Proxy; 5 using NHibernate.Proxy.Map; 6 using NHibernate.Tuple; 7 using NHibernate.Tuple.Entity; 8 using System.Collections.Generic; 9 10 namespace DynamicTableTest.DynamicTable 11 { 12 public class DynamicEntityTuplizer : AbstractEntityTuplizer 13 { 14 private static readonly IInternalLogger log = LoggerProvider.LoggerFor(typeof(PocoEntityTuplizer)); 15 16 private static readonly DynamicModelAccesser Accessor = new DynamicModelAccesser(); 17 private sealed class DynamicModelMapInstantiator : IInstantiator 18 { 19 private readonly string entityName; 20 private readonly HashSet<string> isInstanceEntityNames = new HashSet<string>(); 21 22 private PersistentClass mappingInfo; 23 24 public DynamicModelMapInstantiator() 25 { 26 entityName = null; 27 } 28 29 public DynamicModelMapInstantiator(PersistentClass mappingInfo) 30 { 31 this.mappingInfo = mappingInfo; 32 entityName = mappingInfo.EntityName; 33 isInstanceEntityNames.Add(entityName); 34 if (mappingInfo.HasSubclasses) 35 { 36 foreach (PersistentClass subclassInfo in mappingInfo.SubclassClosureIterator) 37 isInstanceEntityNames.Add(subclassInfo.EntityName); 38 } 39 } 40 41 public object Instantiate(object id) 42 { 43 return Instantiate(); 44 } 45 46 public object Instantiate() 47 { 48 var model = new DynamicTestModel(entityName); 49 return model; 50 } 51 52 public bool IsInstance(object obj) 53 { 54 var that = obj as DynamicTestModel; 55 if (that != null) 56 { 57 if (entityName == null) 58 { 59 return true; 60 } 61 string type = that.EntityName; 62 return type == null || isInstanceEntityNames.Contains(type); 63 } 64 else 65 { 66 return false; 67 } 68 } 69 } 70 71 public DynamicEntityTuplizer(EntityMetamodel entityMetamodel, PersistentClass mappingInfo) 72 : base(entityMetamodel, mappingInfo) 73 { 74 // NH different behavior fo NH-1587 75 Instantiator = BuildInstantiator(mappingInfo); 76 } 77 78 public override System.Type ConcreteProxyClass 79 { 80 get { return typeof(DynamicTestModel); } 81 } 82 83 public override bool IsInstrumented 84 { 85 get { return false; } 86 } 87 88 public override System.Type MappedClass 89 { 90 get { return typeof(DynamicTestModel); } 91 } 92 93 public override EntityMode EntityMode 94 { 95 get { return EntityMode.Map; } 96 } 97 98 protected override IGetter BuildPropertyGetter(NHibernate.Mapping.Property mappedProperty, PersistentClass mappedEntity) 99 {100 return BuildPropertyAccessor(mappedProperty).GetGetter(null, mappedProperty.Name);101 }102 103 104 105 private IPropertyAccessor BuildPropertyAccessor(NHibernate.Mapping.Property property)106 {107 return Accessor;108 }109 110 protected override ISetter BuildPropertySetter(NHibernate.Mapping.Property mappedProperty, PersistentClass mappedEntity)111 {112 return BuildPropertyAccessor(mappedProperty).GetSetter(null, mappedProperty.Name);113 }114 115 protected override IInstantiator BuildInstantiator(PersistentClass mappingInfo)116 {117 return new DynamicModelMapInstantiator(mappingInfo); // new DynamicMapInstantiator(mappingInfo);118 }119 120 protected override IProxyFactory BuildProxyFactory(PersistentClass mappingInfo, IGetter idGetter,121 ISetter idSetter)122 {123 IProxyFactory pf = new MapProxyFactory();124 try125 {126 //TODO: design new lifecycle for ProxyFactory127 pf.PostInstantiate(EntityName, null, null, null, null, null);128 }129 catch (HibernateException he)130 {131 log.Warn("could not create proxy factory for:" + EntityName, he);132 pf = null;133 }134 return pf;135 }136 }137 }
DynamicInterceptor
1 using NHibernate; 2 using NHibernate.Mapping; 3 using System.Collections.Generic; 4 5 namespace DynamicTableTest.DynamicTable 6 { 7 public class DynamicInterceptor : EmptyInterceptor 8 { 9 private readonly string entityName;10 private readonly HashSet<string> isInstanceEntityNames = new HashSet<string>();11 12 public DynamicInterceptor()13 {14 entityName = null;15 }16 17 public DynamicInterceptor(PersistentClass mappingInfo)18 {19 entityName = mappingInfo.EntityName;20 isInstanceEntityNames.Add(entityName);21 if (mappingInfo.HasSubclasses)22 {23 foreach (PersistentClass subclassInfo in mappingInfo.SubclassClosureIterator)24 isInstanceEntityNames.Add(subclassInfo.EntityName);25 }26 }27 28 public override string GetEntityName(object entity)29 {30 var dynamicEntity = entity as DynamicTestModel;31 if (dynamicEntity == null) {32 return base.GetEntityName(entity);33 }34 else35 {36 return dynamicEntity.EntityName;37 }38 }39 }40 }
DynamicModelAccesser
1 using NHibernate.Engine; 2 using NHibernate.Properties; 3 using System; 4 using System.Collections; 5 using System.Reflection; 6 7 namespace DynamicTableTest.DynamicTable 8 { 9 public class DynamicModelAccesser : IPropertyAccessor 10 { 11 private static readonly string CUSTOM_PROPERTY_NAME = "CustomProperties"; 12 private static readonly string AUTO_ID_NAME = "auto_id"; 13 14 public IGetter GetGetter(System.Type theClass, string propertyName) 15 { 16 return new DynamicGetter(propertyName); 17 } 18 19 public ISetter GetSetter(System.Type theClass, string propertyName) 20 { 21 return new DynamicSetter(propertyName); 22 } 23 24 public bool CanAccessThroughReflectionOptimizer 25 { 26 get { return false; } 27 } 28 29 [Serializable] 30 public sealed class DynamicSetter : ISetter 31 { 32 private readonly string name; 33 34 internal DynamicSetter(string name) 35 { 36 this.name = name; 37 } 38 39 public MethodInfo Method 40 { 41 get { return null; } 42 } 43 44 public string PropertyName 45 { 46 get { return null; } 47 } 48 49 public void Set(object target, object value) 50 { 51 if (CUSTOM_PROPERTY_NAME.Equals(name)) 52 { 53 (target as DynamicTestModel).CustomProperties = (IDictionary)value; 54 } 55 else if (AUTO_ID_NAME.Equals(name)) 56 { 57 (target as DynamicTestModel).auto_id = value as string; 58 }
59 else
60 { 61 (target as DynamicTestModel).CustomProperties[name] = value;
62 } 63 } 64 } 65 66 [Serializable] 67 public sealed class DynamicGetter : IGetter 68 { 69 private readonly string name; 70 71 internal DynamicGetter(string name) 72 { 73 this.name = name; 74 } 75 76 public MethodInfo Method 77 { 78 get { return null; } 79 } 80 81 public object GetForInsert(object owner, IDictionary mergeMap, ISessionImplementor session) 82 { 83 return Get(owner); 84 } 85 86 public string PropertyName 87 { 88 get { return null; } 89 } 90 91 public System.Type ReturnType 92 { 93 get { return typeof(object); } 94 } 95 96 public object Get(object target) 97 { 98 if (CUSTOM_PROPERTY_NAME.Equals(name)) 99 {100 return (target as DynamicTestModel).CustomProperties;101 }102 else if (AUTO_ID_NAME.Equals(name))103 {104 return (target as DynamicTestModel).auto_id;105 }106 return (target as DynamicTestModel).CustomProperties[name];107 }108 }109 }110 }
模板hbm.xml
1 <?xml version="1.0" encoding="utf-8" ?> 2 <hibernate-mapping 3 xmlns="urn:nhibernate-mapping-2.2" 4 assembly="@assembly" 5 namespace="@namespace" 6 auto-import="true" 7 default-access="property" 8 default-cascade="none" 9 default-lazy="true">10 11 <class entity-name="@class" table="@table">12 <tuplizer class="DynamicEntityTuplizer" entity-mode="dynamic-map" />13 <id name="auto_id" column="auto_id" type="string">14 <generator class="uuid.hex" />15 </id>16 <dynamic-component insert="true" name="CustomProperties" optimistic-lock="true" unique="false" update="true">17 </dynamic-component>18 </class>19 </hibernate-mapping>
最后是测试代码,QueryOver中where在这里会有问题,改用hql语句实现了
1 using DynamicTableTest.DynamicTable; 2 using System; 3 using System.Linq; 4 5 namespace DynamicTableTest 6 { 7 class Program 8 { 9 static void Main(string[] args)10 {11 DynamicModelMethod();12 13 Console.Read();14 }15 16 private static void DynamicModelMethod()17 {18 var entityName = "Test_Role";19 var columnName = "Name";20 var columnRole = "Role";21 var columnCreateTime = "Create_Time";22 23 var dynamicEntity = new DynamicTestModel(entityName);24 var name = Guid.NewGuid().ToString();25 dynamicEntity.SetValueOfCustomField(columnName, name);26 dynamicEntity.SetValueOfCustomField(columnRole, 31);27 dynamicEntity.SetValueOfCustomField(columnCreateTime, DateTime.Now);28 29 MappingManager.UpdateClassMapping(dynamicEntity);30 HibernateUtil.Instance.Reset();31 32 var session = HibernateUtil.Instance.CurrentSession;33 34 var trans = session.BeginTransaction();35 try36 {37 //add38 var id = session.Save(entityName, dynamicEntity);39 Console.WriteLine("first name: " + name);40 41 //get42 var role = (DynamicTestModel)session.Get(entityName, id);43 var storedName = role.GetValueOfCustomField(columnName);44 Console.WriteLine("second name: "+storedName);45 46 //update47 var newName = Guid.NewGuid().ToString();48 role.SetValueOfCustomField(columnName, newName);49 session.SaveOrUpdate(entityName, role);50 51 //get 52 role = (DynamicTestModel)session.Get(entityName, id);53 storedName = role.GetValueOfCustomField(columnName);54 Console.WriteLine("third name: " + storedName);55 56 //delete57 session.Delete(entityName, role);58 role = (DynamicTestModel)session.Get(entityName, id);59 Console.WriteLine(role == null);60 61 var roles = session.QueryOver<DynamicTestModel>(entityName).List();62 foreach (var roleItem in roles)63 {64 Console.WriteLine(roleItem.ToString());65 }66 Console.WriteLine("###########################################");67 roles = session.CreateQuery(string.Format("from {0} where {1}=‘{2}‘", entityName, columnName, "abc")).Enumerable<DynamicTestModel>().ToList();68 69 foreach (var roleItem in roles)70 {71 Console.WriteLine(roleItem.ToString());72 }73 74 trans.Commit();75 }76 catch (Exception ex)77 {78 trans.Rollback();79 Console.WriteLine(ex.ToString());80 }81 }82 }83 }
Over!
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。