NHibernate issue with assigned string ID and different case chars
I've a problem when save an entity with assigned string Id on NHibernate...I try to explain the issue with an example.
Well, suppose to have an entity on database with ID "AAA", if I execute this statements
ENTITYTYPE entity = Session.Get<ENTITYTYPE>("AAA");开发者_如何转开发
ENTITYTYPE newentity = new ENTITYTYPE() { Id = "aaa" };
Session.Delete(entity);
Session.Save(newentity);
Session.Flush();
On Flush NHibernate raise an exception with this message: "Could not synchronize database state with session" / "Violation of PRIMARY KEY"
It seems to have problem with Case Sensitive ID, if I use "AAA" on Id of "newentity" then it works, but in my situation is not so easy and I've to find an alternative solution.
How can avoid this exception? Can you help me?
I don't know if it is enought but you control it with something like this:
public override bool Equals(object obj)
{
T other = obj as T;
if (other == null)
return false;
// handle the case of comparing two NEW objects
bool otherIsTransient = Equals(other.Id, Guid.Empty);
bool thisIsTransient = Equals(Id, Guid.Empty);
if (otherIsTransient && thisIsTransient)
return ReferenceEquals(other, this);
return other.Id.ToUpper().Equals(Id.ToUpper());
}
using ToUpper() or ToLower() method during compare of your entity, or you can use String.Compare(stringA,strngB,StringComparison.OrdinalIgnoreCase).
If you want more control and if this is your goal, you can create your custom Id generator as described here:
http://nhibernate.info/doc/howto/various/creating-a-custom-id-generator-for-nhibernate.html
updated
have you tried creating a custom GetIgnoreCase(...)?
I think is also possible to override SELECT statement generated by default Get method in your entity mapping file via loader tag like this example:
...
<loader query-ref="loadProducts"/>
</class>
<sql-query name="loadProducts">
<return alias="prod" class="Product" />
<![CDATA[
select
ProductID as {prod.ProductID},
UnitPrice as {prod.UnitPrice},
ProductName as {pod.ProductName}
from Products prod
order by ProductID desc
]]>
You can try to modify the select statement returning an uppercase ID.
updated
After furter investigation I think a way to resolve your problem can be using an Interceptor!
Read here:
http://knol.google.com/k/fabio-maulo/nhibernate-chapter-11-interceptors-and/1nr4enxv3dpeq/14#
more docs here:
http://blog.scooletz.com/2011/02/22/nhibernate-interceptor-magic-tricks-pt-5/
Something like this:
public class TestInterceptor
: EmptyInterceptor, IInterceptor
{
private readonly IInterceptor innerInterceptor;
public TestInterceptor(IInterceptor innerInterceptor)
{
this.innerInterceptor = this.innerInterceptor ?? new EmptyInterceptor();
}
public override object GetEntity(string entityName, object id)
{
if (id is string)
id = id.ToString().ToUpper();
return this.innerInterceptor.GetEntity(entityName, id);
}
}
and register it fluently like this:
return Fluently.Configure()
...
.ExposeConfiguration(c =>{c.Interceptor = new TestInterceptor(c.Interceptor ?? new EmptyInterceptor());})
...
.BuildConfiguration();
精彩评论