- 浏览: 77238 次
文章分类
- 全部博客 (48)
- AOP (0)
- ASP.NET (1)
- C# (0)
- Community Server (0)
- Database (0)
- Design Pattern (3)
- JAVA (1)
- JavaScript (1)
- Linux (1)
- O/R Mapping (0)
- OO (3)
- SQL Server (1)
- VB.NET (0)
- Visual Studio 2005 (2)
- Windows (2)
- WPF (0)
- XML/XSLT (0)
- 常用工具类 (0)
- 人生感悟 (0)
- 算法 (0)
- 转载 (5)
- [网站分类]1.首页原创精华.NET区(包含架构设计、设计模式)(对首页文章的要求:原创、高质量、经过认真思考并精心写作) (3)
- [网站分类]2..NET新手区(用于发表不合适发表在首页的.NET技术文章,包括小经验、小技巧) (15)
- [网站分类]3.非技术区(技术之外的文章,但不要涉及任何政治内容) (2)
- [网站分类]4.其他技术区 (4)
- [网站分类]5.企业信息化 (0)
- [网站分类]6.读书心得区(技术书籍阅读心得、书籍推荐) (0)
- [网站分类]7.提问区(.NET技术方面的提问) (0)
- [网站分类]8.技术转载区(.NET技术文章转载, 请注明原文出处) (1)
- [网站分类]9.求职招聘区(个人求职、企业招聘) (0)
- [网站分类]Dottext区 (0)
- [网站分类]GIS技术 (0)
- [网站分类]IT英才专区(IT职场交流) (0)
- [网站分类]SharePoint (0)
- [网站分类]博客园.NET俱乐部(俱乐部组织与活动方面的文章) (0)
- [网站分类]软件发布区(发布自己开发的代码、软件) (0)
- [网站分类]网站管理区(网站管理方面的疑问、建议、意见, 寻求管理员帮助) (0)
- [网站分类]业界新闻 (0)
最新评论
-
xjw1987524:
这个问题我是弄啦很久,我也试过反编译,不知道为什么就是不成功; ...
支持中文参数的 jspSmartUpload
NHibernate 实体类中重写 Equals() 和 GetHashCode()
在正常的对象操作中,当两个对象都是通过 new 或者其它方式创建出来,尽管它们在属性和行为上是一致的,但我们还是得承认他们是属于不同的两个事物,就像现实世界中的单卵双生的双胞胎虽然各方面都很像,但他们到底还是属于不同的个体。但当这种情况发生在 NHibernate(以下简称NH), 实休类中时,我们就不能这么草率地下结论了,通常实体类中每个实例映射着数据库表中的一行记录,我们知道一个良好设计的数据库表字段中一个唯一标识是必不可少的,那就是主键,主键相当于每个公民的身份证号,必须是唯一且无重复的,不管运行多少次 select * from table where id = @id ,只要 @id 值不改变我们就认为查询出来的是同一行记录,同样的道理映射到实体类中也是主键的属性值相等我们就应该承认它们是相等的,一张身份证它可以有多个复印件,但不管怎样它都是属于同一个人的。
由于 System.Object 中是通过 Equals() 方法来确定两个对象是否相等,因为 Equals() 方法中两个对象具有相同的“值”,那么即使它们不是同一实例,这样的 Equals 实现仍返回 true。两个相同的对象它的 GetHashCode() 结果也必须是相等的,在 MSDN 上也明确指出,“重写 Equals 的类型也必须重写 GetHashCode;否则,Hashtable 可能不正常工作。”“重写 GetHashCode 的派生类还必须重写 Equals,以保证被视为相等的两个对象具有相同的哈希代码;否则,Hashtable 可能不会正常工作。”
下面是引用 Hibernate参考文档 第4章 中对 实现equals()和hashCode() 的解释:
4.3. 实现equals()和hashCode()如果你需要混合使用持久化类(比如,在一个Set中),你必须重载equals() 和 hashCode()方法。
这仅适用于那些在两个不同的Session中装载的对象,Hibernate在单个Session中仅保证JVM 辨别( a == b ,equals()的默认实现)!
就算两个对象a和b实际是同一行数据库内容(它们拥有同样的主键值作为辨识符),我们也不能保证在特定的Session 之外它们是同一个Java实例。
最显而易见的实现equals()/hashCode()方法的办法就是比较两个对象的标识值。如果这个值是同堂的,他们必定是直线同一条数据库行,所以它们是相等的(如果都被加入到Set,在Set中只应该出现一个元素)。不幸的是,我们不能使用这种办法。Hibernate只会对已经持久化的对象赋予标识值,新创建的实例将不会有任何标识符值!我们推荐使用商业关键字相等原则来实现equals()和hashCode()。
商业关键字相等意味着equals()方法只比较那些组成商业关键字的属性,它对应着真实世界中的实例(自然的候选关键字)
下面是实现方法(该方法出自 http://cs.nerdbank.net/blogs/jmpinline/archive/2006/01/24/126.aspx ):
/// Tests whether this and another object are equal in a way that
/// will still pass when proxy objects are being used.
/// </summary>
public override bool Equals(object obj)
{
ClassNameHere other = obj as ClassNameHere;
if (other == null) return false;
if (Id == 0 && other.Id == 0)
return (object)this == other;
else
return Id == other.Id;
}
public override int GetHashCode()
{
if (Id == 0) return base.GetHashCode();
string stringRepresentation = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "#" + Id.ToString(); return stringRepresentation.GetHashCode();
}
伴随着 .NET 2.0 的发布,加入了泛型代码中 default 关键字,我们可以把 snippet 做得更加通用而不仅限于 Int 数据类型,
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Entity Equals and GetHashCode</Title>
<Shortcut>nheq</Shortcut>
<Author>yyw</Author>
<HelpUrl>
http://www.cnblogs.com/yyw84/archive/2006/09/17/506695.html
http://cs.nerdbank.net/blogs/jmpinline/archive/2006/01/24/126.aspx
</HelpUrl>
<Description></Description>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
<Description>Inserts the Equals and GetHashCode methods that NHibernate requires to run correctly.</Description>
</Header>
<Snippet>
<Declarations>
<Literal Editable="true">
<ID>type</ID>
<ToolTip>The name of the class being injected.</ToolTip>
<Default>ClassName</Default>
</Literal>
<Literal>
<ID>id</ID>
<ToolTip>主键ID</ToolTip>
<Default>Id</Default>
</Literal>
<Literal>
<ID>idtype</ID>
<ToolTip>主键属性类型</ToolTip>
<Default>int</Default>
</Literal>
</Declarations>
<Code Language="CSharp">
<![CDATA[#region Equals and GetHashCode
/// <summary>
/// Tests whether this and another object are equal in a way that
/// will still pass when proxy objects are being used.
/// </summary>
public override bool Equals(object obj)
{
$type$ other = obj as $type$;
if (other == null)
return false;
if ($id$== default($idtype$) && other.$id$ == default($idtype$))
return (object)this == other;
else
return $id$ == other.$id$;
}
public override int GetHashCode()
{
if ($id$ == default($idtype$))
return base.GetHashCode();
string stringRepresentation = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "#" + $id$.ToString();
return stringRepresentation.GetHashCode();
}
#endregion
$end$]]>
</Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
为了做到一劳永逸,接下来要做的事就是把它添加到我的 CodeSmith 模板中了,添加的内容如下:
/**//// <summary>
/// Tests whether this and another object are equal in a way that
/// will still pass when proxy objects are being used.
/// </summary>
public override bool Equals(object obj)
{
<%= ClassName(SourceTable) %> other = obj as <%= ClassName(SourceTable) %>;
if (other == null)
return false;
if (<%= IdName(SourceTable) %> == default(<%= IdMemberType(SourceTable) %>) && other.<%= IdName(SourceTable) %> == default(<%= IdMemberType(SourceTable) %>))
return (object)this == other;
else
return <%= IdName(SourceTable) %> == other.<%= IdName(SourceTable) %>;
}
public override int GetHashCode()
{
if (<%= IdName(SourceTable) %> == default(<%= IdMemberType(SourceTable) %>))
return base.GetHashCode();
string stringRepresentation = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.FullName + "#" + <%= IdName(SourceTable) %>.ToString();
return stringRepresentation.GetHashCode();
}
#endregion
事情都已经做到这个份上也该收场了,虽然只是一些小技巧,也希望能给大家带来方便,提高生产效率。。。 :)
发表评论
-
获取某目录下的所有文件(包括子目录下文件)的数量(C#)
2005-11-04 17:27 3973以前写过一个通过计算目录遍历所有文件和子目录的方法来获得某目录 ... -
Visual Studio 2005 试用笔记
2005-11-06 21:36 911今天开始用上了 VS 2005 ... -
C#面向对象设计模式纵横谈(2):Singleton 单件(创建型模式) 笔记
2005-11-09 22:52 1298(很喜欢李建忠老师的这个讲座,可惜暂时没更多的了,继续关注 M ... -
利用视图管理器高效编写 SQL SELECT 语句
2006-02-19 13:27 921献给初学者,老鸟别扔砖头 编写 ... -
将Web站点下的绝对路径转换为虚拟路径
2006-05-07 12:48 1178很经常使用到的一个功能,但在在网上却一直没有找到相关的解决方法 ... -
比较高效地实现从两个不同数组中提取相同部分组成新的数组(只支持Int类型) [C#]
2006-05-13 22:17 4017有时候我们需要从两个不同数组中提取出相同的部分 ... -
基于 .NET 2.0 System.Net.Mail namespace 的邮件发送组件
2006-05-17 13:11 1863一个基于 .NET 2.0 System.Net.Mail n ... -
从 CCS 1.1 升级到 CS 2.0 所遇到的问题和部分解决方法
2006-06-16 12:58 799整理了一下,记录在这 ... -
.NET Enum The Next Level
2006-08-20 17:15 1147声明:本文内容出自:http://www.codeprojec ... -
C# 中实现随机时间的获取
2006-09-07 17:31 1321原理其实非常简单,取出两个时间差的秒数,再在0到该秒数 ... -
初识 db4o
2006-10-25 21:41 920今天早上收到 IBM developerWork ... -
Spring.Net AOP 学习之旅: 使用 Throws Advice 处理异常
2006-10-30 21:12 4222写在前头:本文示例和部分文字来自《Sprin ... -
.NET 1.1 下不使用 System.Web.Mail.SmtpMail 发送邮件的其它选择
2006-12-22 20:35 1221最近工作原因需要维护 ASP.NET 1.1 的程 ... -
.NET 中的 委托与事件
2006-12-27 10:10 1908一、什么是委托 ...
相关推荐
CodeSmith 是一个模板驱动的代码生成工具,它允许用户通过自定义模板来生成各种代码,包括但不限于数据库访问层、业务逻辑层和实体类。通过使用此模板,开发者可以节省大量的手动编码时间,专注于业务逻辑的实现,...
在这个主题中,“根据NHibernate实体生成简单控件”指的是利用NHibernate定义的实体类来创建用户界面中的控件,如文本框、下拉列表等,以便于数据的展示和输入。这种方式可以极大地提高开发效率,避免手动为每个实体...
总结来说,"NHibernate2.0 实体类和配置文件生成模板"是CodeSmith工具的一个应用实例,它简化了基于NHibernate的.NET项目中实体类和配置文件的创建过程,提升了开发效率。理解并熟练使用这些模板,有助于提升开发者...
2. 一致性保证:映射文件确保了数据库表结构和实体类的一致性,减少错误。 3. 可维护性:当数据库结构发生变化时,只需更新映射文件,然后重新生成代码即可。 在实际应用中,开发者需要了解如何配置和使用`Hbm2...
然而,手动编写每个实体类的映射文件(.hbm.xml)或使用特性注解(.NET 4.0及以后版本)会消耗大量时间。这就是“nhibernate映射类代码生成器”发挥作用的地方。 这个代码生成器的主要目标是自动化创建与数据库表...
"NHibernate代码生成模板v1_1"着重于修复了v1.0版本的一个主要问题,即在处理复合主键时,实体类在运行时会引发Nhibernate错误。在数据库设计中,复合主键是指由两个或更多列共同组成的唯一标识符。在ORM框架中,...
在IT行业中,实体类是软件开发中的重要组成部分,特别是在基于对象的编程语言如C#中。实体类通常代表数据库中的表,它们封装了数据并提供了操作这些数据的方法。手动创建和维护这些实体类可能会非常耗时,尤其是在...
例如,Entity Framework的`Scaffold-DbContext`命令行工具可以自动从数据库创建上下文类和实体类。只需运行以下命令,替换合适的连接字符串和数据库提供者: ```bash dotnet ef dbcontext scaffold "Server=...
通过使用这类生成工具,开发人员可以从数据库中读取表结构信息,一键生成对应的实体类,这些类可以直接被ORM框架如Entity Framework或NHibernate使用,实现数据访问层的快速构建。 工具的主要功能包括: 1. 单表...
3. **实体类映射**:理解如何使用Hibernate的注解或XML映射文件将C#类映射到数据库表。 4. **会话管理**:掌握Session接口的使用,它是与数据库交互的主要接口,负责保存、加载和更新对象。 5. **事务处理**:学习...
**Nhibernate代码生成器** 是一个工具,它的主要功能是自动生成Nhibernate实体类和映射文件,从而极大地简化了开发过程。在使用Nhibernate进行对象关系映射(ORM)时,手动创建每个实体类和对应的映射文件是一项繁琐...
在ASP.NET和C#环境中,实体类生成器通常会集成在开发环境中,如Visual Studio,通过ORM(对象关系映射)框架如Entity Framework或NHibernate来工作。这些工具能够根据数据库中的表结构自动生成对应的C#类,类中的...
1. **映射文件**: 使用XML(如`hibernate-mapping`)或Fluent NHibernate进行实体类与数据库表之间的映射。 2. **标识符**: 设置主键,可以使用自动增长、自定义ID生成器等策略。 3. **属性映射**: 包括字段类型、...
在标题和描述中提到的“nhibernate 由类文件,映射文件自动生成表的 源代码”,指的是使用NHibernate的SchemaExport工具或编程方式,根据定义的类和映射文件自动创建数据库表的机制。以下是对这个主题的详细解释: ...
在C#中,为了实现更高效的数据访问,实体类通常会配合ORM(对象关系映射)框架,如Entity Framework或NHibernate使用。这些框架允许开发者以面向对象的方式操作数据库,而无需编写大量的SQL语句。实体类生成器在生成...
实现 Equals() 和 GetHashCode() 方法 4.4. 持久化生命周期(Lifecycle)中的回调(Callbacks) 4.5. 合法性验证(IValidatable)回调 5. 对象/关系数据库映射基础(Basic O/R Mapping) 5.1. 映射定义...
C#实体类代码生成器是一种工具,用于自动化创建C#编程中的数据模型类,也称为实体类。在软件开发中,尤其是涉及到数据库交互时,实体类是必不可少的一部分,它们代表了数据库表中的记录,提供了与数据库对象进行交互...
9. **事件和拦截器**: NHibernate提供了一套事件系统和拦截器,允许在特定操作(如对象加载、保存、更新、删除等)前后插入自定义代码。 10. **版本控制**: NHibernate支持乐观锁和悲观锁,以防止并发访问时的数据...
`NHibernate_VirtualEntity.cst`模板可能是一个扩展或增强版的实体类模板,其中的"Virtual"通常意味着属性使用了虚方法(virtual),这在Nhibernate的懒加载(Lazy Loading)机制中很重要。当实体的某个属性标记为...
例如,实体类的属性名称、类型和映射文件中的字段映射是动态的,而类名、文件名等可能是固定的。 - 编写模板语言代码,如使用Emit或Expression语法,来定义模板的生成规则。 - 测试模板,通过提供不同的输入(如...