The background
My model looks like the following: (writing fields instead of properties for simplicity)
public class Entity {
public long Id;
public string Name;
public Entity Parent;
}
Essential FNH mapping
Map(x => x.Name)
.Not.Nullable()
.UniqueKey("Child");
References(x => x.Parent)
.Cascade.None()
.UniqueKey("Child");
SQL
create table `Entity` (Id BIGINT not null, Name VARCHAR(255) not null, Parent_id BIGINT, primary key (Id),unique (Name, Parent_id))
And that's fine. I don't want omonimities between children of the same entities (so two entities of different parent may have same name). By the way, bear in mind that Parent_id
is nullable
What I need to do
I want to enforce a check before inserting a new entity into the DB. Instead of catching an exception I want to fire a query (but I think it reduces performance...) to check if an entity with same name and parent of newcoming exists in order to throw a decent exception. Despite performance, it's still a chance to learn something new about LINQ providers
In plain old SQL I would do
SELECT Id FROM entity WHERE Name = ? AND Parent_id = ?
and this correctly supports NULL ids
What I tried (and failed, otherwise I wouldn't be here)
var exInput = (from Entity entity in entityRepository.Query()
where entity.Name.ToLowerInvariant() == _newEntity.Name.ToLowerInvariant()
&& entity.Parent.Equals(_newEntity.Parent)
select new { ParentName = entity.Parent != null ? entity.Parent.Name : null }).FirstOrDefault();
I thought NHibernate could be smart enough to accept a null value as _newEntity.Parent
and also smart enough to read entity.Parent.Equals
as an expression instead of a method call (which fails in case of null).
Anyway that's not the problem
The error
System.NotSupportedException: Boolean Equals(System.Object)
I know NHibernate LINQ is not a full LINQ provider and doesn't support all methods Entity Framework supports. So I could expect that. Obviously, I can workaround by first selecting entity by name and then check if both parents are null or if they Equals()
(I overloaded Equals
to check Id)
The question
Given that I want NHibernate to generate SQL as closest as possible to the above WHERE
clause, what should I do? Is there a different LINQ syntax to use or should I extend the LINQ provider?
I was thinking about extending LINQ provider, for which I have found some documentation. It is my opinion that if the operands of comparison are of the same identity we can simply match their ID (and if one of the entities is null
generate NULL
identity in HQL). In this case, did anyone try an implementation to share?