I'm facing some issues trying to model my business logic using NHibernate Fluent mapping.
I've a entity model like this:
public class Request
{
...
public virtual Response Response {get; set;}
}
public class Response
{
...
public virtual Request Request {get; set;}
}
My Request
entity should be able to exist without a Response
entity, and vice versa my Response
entity should be able to exist without a Request
. Can this be mapped as a one-to-one mapping? I know that is seems wired that a Response
can exist without a Request
, but that could happen in my situation.
I have read the article I Think You Mean a Many-to-one, Sir, but I still think that a many-to-one mapping is not the right thing for me, as none of my entities should have a list of either Responses or Requests.
How should this situation be mapped?
EDIT 1
My Fluent map using the foreign key association from How to do a fluent nhibernate one to one mapping?:
public RequestMap()
{
Id(x => x.Id).GeneratedBy.Guid();
References(x => x.Response, "ResponseId").Unique().Cascade.All();
}
public ResponseMap()
{
Id(x => x.Id).GeneratedBy.Guid();
HasOne(x => x.Request).Cascade.All().PropertyRef(x => x.Response);
}
This seems to work in many situations, but when I try to add multiple Request
entities without a reference to a Response
entity, I get this error:
System.Data.SqlClient.SqlException : Violation of UNIQUE KEY constraint 'UQ__Request__346FA94719588CEC'. Cannot insert duplicate key in object 'dbo.Request'. The duplicate key value is (). The statement has been terminated.
EDIT 2
public RequestMap()
{
Id(x => x.Id).GeneratedBy.Guid();
HasOne(x => x.Response).Cascade.All().PropertyRef(x => x.Request);
}
public ResponseMap()
{
Id(x => x.Id).GeneratedBy.Guid();
References(x => x.Request, "RequestId").Cascade.All();
}
Using this mapping, the mapping between the objects is not persisted when doing request.Response = response;
. Should I make this setter protected?
The issue with your EDIT 1 comes from these facts:
Request
table does have a unique constraint over the column "ResponseId". I.e. each row must have different valueRequests
stored without reference to Response do have NULL
instead of any value... all of them. And that breaks the above requirement to have each row uniqueSolution in this case would be to remove the unique key on the DB level from the ResponseId
column. Because this is what we need (Request without Response). I.e. few concurrent NULL values in ReponseId should be allowed.
But what is a bit confusing me, is the naming: Reponse/Request
It seems to me, that Request (from my web development experience) is the trigger, the first one. And if all goes ok, there is a Response sent back. Should not your mapping be inversed? That the Response table contains the RequestId?
I've seen this statement in the question:
My Request entity should be able to exist without a Response entity, and vice versa my Response entity should be able to exist without a Request
Well, so ... let's assume that: the Response
can NOT live without the Request
... then your mapping (but inversed) should work even with the Unique key constraing.
And what is even more important, then the pure one-to-one
mapping will work, because these two can share the Primary key (generated by Request, consumed by Response)