NHibernate 知識點整理
1、實體bool類型屬性與數據庫映射。如實體中有bool屬性IsDelete.配置如下
<property column="IsDelete" name="IsDelete" type="YesNo" ></property>
或者
<property name="Deleted" type="NHibernate.Type.YesNoType,NHibernate">
<column name="Deleted" sql-type="char(1)" default="0" not-null="true"></column>
</property>
2、若將數據寫入到表時,希望某個字段不被寫入則如下映射
<property column="IsDelete" name="IsDelete" insert="false"></property>
3、兩個對象之間多對多時,生成兩個表之間的映射關系表.如一下生成 人員與公司之間的映射關系表UserCompanyMap.UserID與CompanyID作為聯合主鍵
<set name="Companies" table="UserCompanyMap" >
<key column="UserID" />
<many-to-many column="CompanyID" class="Domain.Company,Domain" />
</set>
4、通過ICritetia接口做關聯查詢;如有many-to-one關系的Profile和Department。現在希望通過sql直接查詢返回dto ProfileDTO 。sql如下;
SELECT p.ItemID, p.Name, p.Summary, d.ItemID, d.Name FROM Profile p inner join Department d on p.DepartmentID = d.ItemID
public class ProfileDTO { private int _itemID; private int _departmentID; private string _departmentName; private string _name; private string _summary; public virtual int ItemID { get { return _itemID; } set { _itemID = value; } } public virtual int DepartmentID { get { return _departmentID; } set { _departmentID = value; } } public string DepartmentName { get { return _departmentName; } set { _departmentName = value; } } public string Name { get { return _name; } set { _name = value; } } public string Summary { get { return _summary; } set { _summary = value; } } }
public static IList List() { ICriteria criteriaSelect = Persistence.Session.CreateCriteria(typeof(Profile)); criteriaSelect.CreateAlias("Department", "d"); criteriaSelect.SetProjection( Projections.ProjectionList() .Add(Projections.Property("ItemID"), "ItemID") .Add(Projections.Property("Name"), "Name") .Add(Projections.Property("Summary"), "Summary") .Add(Projections.Property("d.ItemID"), "DepartmentID") .Add(Projections.Property("d.Name"), "DepartmentName")); criteriaSelect.AddOrder(Order.Asc("Name")); criteriaSelect.SetResultTransformer(NHibernate.Transform.Transformers.AliasToBean(typeof(ProfileDTO))); return criteriaSelect.List(); }
5、ICriteia 接口進行數據分頁查詢時,一般情況下,可能如下使用:
ICriteria criteria = session.CreateCriteria(typeof(T));
foreach (ICriterion cri in queryConditions) { criteria.Add(cri); } ICriteria criteriaRowCount = CriteriaTransformer.Clone(criteria); recordCount = criteriaRowCount.SetProjection(Projections.RowCount()) .UniqueResult<int>(); foreach (ICriterion cri in queryConditions) { detachedCriteria.Add(cri); }
if (IsPage)
{
int skipCount=(pageIndex - 1)*pageSize;
criteria.SetFirstResult(skipCount).SetMaxResults(*pageSize);
}
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer());
return criteria.List<T>();
但是這樣可能會導致數據分頁出現問題。如果實體T沒有和其他表的關聯關系,這樣取數據顯然是可行的。但是如果關聯過多,而T又不是領域里的聚合根,則可能導致分頁問題。
原因是NHibernate使用left join 關聯多表進行查詢時,查詢出滿足條件的數據,然后按照SetFirstResult(skipCount).SetMaxResults(*pageSize)進行獲取,然后去重,再顯
示,這樣在過濾掉重復數據后,返回的數據就會比pageSize少。如果pageSize比NHibernate進行left join 后的結果還多的話,那就沒有問題。但是一旦pageSize少于left join的
記錄數,則分頁還存在問題.
解決辦法:
ICriteria criteria = session.CreateCriteria(typeof(T)); foreach (ICriterion cri in queryConditions) { criteria.Add(cri); } ICriteria criteriaRowCount = CriteriaTransformer.Clone(criteria); recordCount = criteriaRowCount.SetProjection(Projections.RowCount()) .UniqueResult<int>(); int skipCount = (pageIndex - 1)*pageSize; criteria.AddOrder(new Order(orderField, isAscending)); DetachedCriteria detachedCriteria = DetachedCriteria.For<T>(); detachedCriteria.SetProjection(Projections.Distinct(Projections.Id())); foreach (ICriterion cri in queryConditions) { detachedCriteria.Add(cri); } List<object> list;
if (IsPage)list = detachedCriteria.GetExecutableCriteria(session).SetFirstResult(skipCount).SetMaxResults(pageSize).List<object>().ToList();
else list = detachedCriteria.GetExecutableCriteria(session).List<object>().ToList();
criteria.Add(Restrictions.In(GetIndentity<T>(), list));//GetIndentity<T>() 獲取實體標識名,即對應數據庫主鍵的實體屬性名稱
criteria.SetResultTransformer(new DistinctRootEntityResultTransformer());
return criteria.List<T>();
6、持久化枚舉類型
<property name="HouseType">
<column name="HouseType" sql-type="varchar(10)" default="0" not-null="true"></column>
</property>
7、Hql查詢直接返回對象
const string hql = @"SELECT new KeyValuePair(COUNT(log.Point)
,user.DepartmentName)
FROM Log log ,User user
WHERE log.UserGuid=user.UserGuid
GROUP BY user.DepartName";
IQuery query = session.CreateQuery(hql);
return query.List<KeyValuePair>();
同時需要給KeyValuePair定義映射,(不需要映射到表)如:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="" namespace=""> <import class="" /> </hibernate-mapping>
8、NHibernate的日志不影響你使用Log4Net寫日志
<?xml version="1.0" encoding="utf-8" ?> <log4net> <root> <!--如果只需要看看Sql設置INFO就夠了,如果你要調試可以設置為DEBUG或ALL--> <priority value="INFO" /> <appender-ref ref="rollingFile" /> </root> <logger name="myLog"> <level value="INFO" /> <appender-ref ref="rollingFile1" /> </logger> <appender name="rollingFile" type="log4net.Appender.RollingFileAppender,log4net" > <param name="File" value="log.txt" /> <param name="AppendToFile" value="false" /> <param name="RollingStyle" value="Date" /> <param name="DatePattern" value="yyyy.MM.dd" /> <param name="StaticLogFileName" value="true" /> <layout type="log4net.Layout.PatternLayout,log4net"> <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] <%X{auth}> - %m%n" /> </layout> </appender> <appender name="rollingFile1" type="log4net.Appender.RollingFileAppender,log4net" > <param name="File" value="log1.txt" /> <param name="AppendToFile" value="false" /> <param name="RollingStyle" value="Date" /> <param name="DatePattern" value="yyyy.MM.dd" /> <param name="StaticLogFileName" value="true" /> <layout type="log4net.Layout.PatternLayout,log4net"> <param name="ConversionPattern" value="%d [%t] %-5p %c [%x] <%X{auth}> - %m%n" /> </layout> </appender> </log4net>
使用Log4Net
ILog Log= LogManager.GetLogger("myLog");
Log.Info("記錄日志");
9、配置C# Decimal類型
<column name="totalPrice" precision="22" scale="0" />
10、配置屬性說明:
1)<property>元素 insert屬性:設置為false,在insert語句中不包含這個字段,表示永遠不會被插入,默認true
2)<property>元素 update屬性:設置為false,在update語句中不包含這個字段,表示永遠不會被修改,默認true
3)<class>元素 mutable屬性:設置為false就是把所有的<property>元素的update屬性設置為了false,說明這個對象不會被更新,默認true
4)<property>元素 dynamic-insert屬性:設置為true,表示insert對象的時候,生成動態的insert語句,如果這個字段的值是null就不會加入到insert語句當中.默認false
5)<property>元素 dynamic-update屬性,設置為true,表示update對象的時候,生成動態的update語句,如果這個字段的值是null就不會被加入到update語句中,默認false
6)<class>元素 dynamic-insert屬性:設置為true,表示把所有的<property>元素的dynamic-insert屬性設置為true,默認false
7)<class>元素 dynamic-update屬性:設置為true,表示把所有的<property>元素的dynamic-update屬性設置為true,默認false
參考:
浙公網安備 33010602011771號