- 浏览: 78787 次
文章分类
- 全部博客 (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 3993以前写过一个通过计算目录遍历所有文件和子目录的方法来获得某目录 ... -
Visual Studio 2005 试用笔记
2005-11-06 21:36 938今天开始用上了 VS 2005 ... -
C#面向对象设计模式纵横谈(2):Singleton 单件(创建型模式) 笔记
2005-11-09 22:52 1315(很喜欢李建忠老师的这个讲座,可惜暂时没更多的了,继续关注 M ... -
利用视图管理器高效编写 SQL SELECT 语句
2006-02-19 13:27 959献给初学者,老鸟别扔砖头 编写 ... -
将Web站点下的绝对路径转换为虚拟路径
2006-05-07 12:48 1209很经常使用到的一个功能,但在在网上却一直没有找到相关的解决方法 ... -
比较高效地实现从两个不同数组中提取相同部分组成新的数组(只支持Int类型) [C#]
2006-05-13 22:17 4047有时候我们需要从两个不同数组中提取出相同的部分 ... -
基于 .NET 2.0 System.Net.Mail namespace 的邮件发送组件
2006-05-17 13:11 1888一个基于 .NET 2.0 System.Net.Mail n ... -
从 CCS 1.1 升级到 CS 2.0 所遇到的问题和部分解决方法
2006-06-16 12:58 828整理了一下,记录在这 ... -
.NET Enum The Next Level
2006-08-20 17:15 1172声明:本文内容出自:http://www.codeprojec ... -
C# 中实现随机时间的获取
2006-09-07 17:31 1368原理其实非常简单,取出两个时间差的秒数,再在0到该秒数 ... -
初识 db4o
2006-10-25 21:41 942今天早上收到 IBM developerWork ... -
Spring.Net AOP 学习之旅: 使用 Throws Advice 处理异常
2006-10-30 21:12 4339写在前头:本文示例和部分文字来自《Sprin ... -
.NET 1.1 下不使用 System.Web.Mail.SmtpMail 发送邮件的其它选择
2006-12-22 20:35 1246最近工作原因需要维护 ASP.NET 1.1 的程 ... -
.NET 中的 委托与事件
2006-12-27 10:10 1933一、什么是委托 ...
相关推荐
例如,添加属性验证规则、自定义导航属性(关联其他表的实体)、重写Equals和GetHashCode方法以支持对象比较等。 5. **Repository模式**:为了进一步解耦数据访问层和业务逻辑层,我们可以采用Repository模式。...
实现 Equals() 和 GetHashCode() 方法 4.4. 持久化生命周期(Lifecycle)中的回调(Callbacks) 4.5. 合法性验证(IValidatable)回调 5. 对象/关系数据库映射基础(Basic O/R Mapping) 5.1. 映射定义...
- **对象比较**:重写Equals()和GetHashCode()方法以支持对象的比较和散列计算。 ##### 4.4 动态模型 - **动态类型**:使用动态类型来简化对象的创建和操作。 ##### 4.5 Tuplizers - **对象转换**:Tuplizer用于将...
- **4.3 实现 Equals() 和 GetHashCode()**:说明了为什么实体类应该重写这两个方法,并给出了正确的实现方式。 - **4.4 生命周期回调**:列举了 NHibernate 支持的几种生命周期事件回调,如 onPreInsert、...
3. **实现 Equals() 和 GetHashCode() 方法**:为了确保实体类能正确地进行相等性比较和散列。 4. **生命周期回调**:探讨了如何利用 NHibernate 提供的事件回调机制。 5. **IValidatable 回调**:介绍了一种验证...
**4.3 实现Equals()和GetHashCode()方法** 为了确保NHibernate能够正确识别相同的对象实例,需要正确地重写这两个方法。这部分内容详细介绍了如何实现以及为什么这么做很重要。 **4.4 动态模型** 动态模型允许在...
4.3. 实现 Equals() 和 GetHashCode() 方法 4.4. 持久化生命周期(Lifecycle)中的回调(Callbacks) 4.5. 合法性验证(IValidatable)回调 5. 对象/关系数据库映射基础(Basic O/R Mapping) 5.1. 映射定义(Mapping...
实现Equals()和GetHashCode() 为了确保实体的正确比较和哈希计算,需要重写这两个方法。 #### 4.4. 生命周期回调 生命周期回调允许在实体生命周期的不同阶段执行特定的操作,如初始化、加载等。 #### 4.5. ...
在实际开发中,当数据库结构发生变化时,通过此工具可以快速更新相关的实体类,避免手动修改大量代码,节省了大量的时间和精力。 使用【VB/C#.Net实体代码生成工具】,开发者可以指定连接到的数据库,选择需要生成...
4.3. 实现 Equals() 和 GetHashCode() 方法 4.4. 持久化生命周期(Lifecycle)中的回调(Callbacks) 4.5. 合法性验证(IValidatable)回调 5. 对象/关系数据库映射基础(Basic O/R Mapping) 5.1. 映射定义(Mapping...
开发者可以通过这个模板自定义实体类的属性(对应数据库字段),并实现如ToString、Equals、GetHashCode等方法。 3. **AutoEntity.cst**:这个名字暗示这可能是一个自动化的实体生成模板,可能包含了更复杂的逻辑,...