Creating a map for relationship key besides using object property - nhibernate

I have a Note class which has a relationship through Client class, and therefore has a property
public virtual Client Client {get; set;}
but how can I add a map to the client_id column, for example having
public virtual int? ClientId {get; set;}

You don't.
If you need to get the value of the FK, you can just do this:
var clientId = note.Client == null? (int?)null : note.Client.Id;
Accessing the id will not cause loading of the Client proxy.
If you need to set the value (and you have an id):
note.Client = session.Load<Client>(clientId);

In the mapping class you would have:
Map(x => x.ClientId);

Related

ASP.NET Core: model invalid due to related ICollections

When submitting my post request, ModelState.IsValid is always false due to the related entities being empty.
[Key]
[Required()]
public int ID {get; set;}
[MaxLength(20)]
[Required()]
public string NAME {get; set;}
public ICollection<ActorMovieJunction> NameJobJunction {get; set;}
Both the ID and the NAME show up as valid in the state model, but NameJobJunction being "null" creates an error.
I'm also using the [BindProperty] tag
I think the problem is a new nullable feature net6. I highly recommend you to remove it or comment in project properties
<!--<Nullable>enable</Nullable>-->
Or you will have to mark all nullable properties as nullable.
public ICollection<ActorMovieJunction>? NameJobJunction {get; set;}
and IMHO never use [Bind] in the controller action parameters.
You can try to give a default value to NameJobJunction:
public ICollection<ActorMovieJunction> NameJobJunction {get; set;}=new List<ActorMovieJunction>();

Mapping Tables with shared foreign key in one to one relationship?

What is best way to map following classes?
I have classes where communication is "base" class as it contains shared data for either option. There can be only communication to ComSms or to ComEmail. The problem is i am unsure how to proceed with the mapping.
I would like if at all possible use one repository for accessing the Objects.
Class Set Up
public interface ICommunication
{
}
public Communication: ICommunication{
//PK and FK on this item
public virtual int CommunicationId{get;set;}
public virtual string Name {get;set;}
public virtual string Surname {get;set;}
public virtual DateTime Date{get;set;}
//I am expecting to switch on type between ComSms and ComEmail
public virtual Type {get;set;}
}
public ComSms : Communication{
public virtual string Number {get;set;}
public virtual string Text {get;set;}
}
public ComEmail : Communication{
public virtual string Subject{get;set;}
public virtual string Body {get;set;}
public virtual string Address {get;set;}
}
Database
Imagined usage
ICommunication smsToSave = new ComSms()
smsToSave.Name = "UserName";
smsToSave.Surname ="UserSurname";
smsToSave.Date = DateTime.Now;
smsToSave.Type = 1;
smsToSave.Number ="123456789";
smsToSave.Text = "Hello boys";
CommunicationRepository.Save(smsToSave)
I don't have time to write out any mappings but what you need is a discriminator. This would allow you to say have a CommunicationType foreign key in your table that could link to either the Sms or Email table. The nice thing about discriminators is that NHibernate takes care of everything for you.
And yes, seeing as your aggregate root is Communication then you could use one repository for accessing either of your communication types.
ok
i have resolved it by separated repositories that handles ever part of it instead
i could not bind it correctly, so chosen to go around the problem.
if you find any way of doing this please let me know

FluentNhibernate Mapping of lookup table in to properties of Parent Object

Using FluentNhiberante is there a way to map the following:
Parent Table (Employee)
EmployeeId INT Primary Key
FirstName
LastName
EmployeeTypeId
Lookup Table (EmployeeType)
EmployeeTypeId INT Primary Key
EmployeeTypeDescription
My class is defined as:
public class Employee
{
int EmployeeId {get; set;}
...
string EmployeeTypeDescription {get; set;}
}
Is there a way via the FluentNhibernate mapping to populate the EmployeeTypeDescription property in the Employee object from the EmployeeTypeDescription table by looking up using the EmployeeTypeId column in Employee?
I'm pretty sure the normal and proper way to do this is by using References in the mapping file and then by adding a EmployeeType property to the Employee class and accessing the description using Employee.EmployeeType.EmployeeTypeDescription. I'm unable to change the code to do that at this time so am wondering how to just set the EmployeeTypeDescription property for now.
it should be possible tweaking the examplecode below:
public class EmployeeMap : ClassMap<Employee>
{
public EmployeeMap()
{
...
Join("EmployeeType", join =>
{
join.KeyColumn("EmployeeTypeId");
join.Map(k => k.TherapieOK, "somecolumn"));
}
...
}
}
You can map the class to a view.
You're correct as far as the normal way to do this.

StaleStateException when changing id in nhibernate

Very new to NHibernate so I expect there will be a quick fix here.
The code I'm looking at has an unorthodox design.
public class Partner
{
public virtual int Id { get; set;} //note the set is not private
public virtual String Name { get; set;}
}
and is mapped with FluentNhibernate's Automappings
When Partner is created its Id is 0 but when
I call Flush to persist to the db:
CurrentSession.SaveOrUpdate(obj);
CurrentSession.Flush();
I get a Unexpected row count: 0; expected: 1 StaleStateException
I'm assuming its because NHibernate doesn't like me changing the Primary Key, Id.
In this case I need to. How can I configure NH to let me achieve this abomination?
You can do the update with HQL:
session.CreateQuery("update Partner set Id = :newId where Id = :oldId")
.SetParameter("newId", newId)
.SetParameter("oldId", oldId)
.ExecuteUpdate();
I suggest that you Evict the entity from the session, or use a stateless one if you are going to update the Id.

Mapping a dictionary in Fluent Nhibernate through a secondary key

I have a legacy DB which uses a guid to map children to the parent entity.
In my domain layer, I'd prefer to obscure this quirk, so I'd like to have my parent entity look like this:
public class Parent
{
virtual public int Id {get; protected set; }
virtual public string ParentContent { get; set; }
virtual public Guid ReferenceId { get; set; }
virtual public IDictionary<int,Child> Children { get; set; }
}
public class Child
{
virtual public int Id { get; protected set; }
virtual public Parent { get; set; }
virtual public string ChildContent { get; set; }
}
The parent would then map each Child.Id to Child in the Children dictionary. The Child mapping works fine, but I can't seem to find a reasonable mapping for the parent.
A field named ParentReferenceID exists in both Parent and Child tables, so I've attempted to map this with something like this:
mapping.HasMany<Broker>(x => x.Children)
.Table("Child")
.KeyColumn("ParentReferenceID")
.Inverse()
.AsMap<long>(index=>index.Id,val=>val.Type<Broker>());
Unfortunately, this produces an error:
The type or method has 2 generic parameter(s), but 1 generic argument(s) were provided. A generic argument must be provided for each generic parameter.
To simplify my problem, I started by trying Bag semantics, replacing the Parent's IDictionary with an IList. This was mapped using something like:
mapping.HasMany<Broker>(x => x.Brokers)
.Table("Child")
.KeyColumn("ParentReferenceId")
.Inverse()
.AsBag();
That produces the more obvious exception,
System.Data.SqlClient.SqlException: Operand type clash: uniqueidentifier is incompatible with int
Unfortunately, I can't seem to figure out the right way to tell it to join on the ReferenceID field. What's the right way to do that? I'd prefer the dictionary, but I'd be reasonably happy if I could even get the bag to work.
For clarity, I'm using a build of Fluent that is bundled with a recent SharpArchitecture pulled from git. The Fluent dll is marked version 1.0.0.594, but if a more recent build would help, I'm flexible.
Further digging has led me to a solution for the Bag case, though the dictionary is still giving me a bit of trouble.
The solution requires a patch to Fluent NHibernate's OneToManyPart mapping class. (Hat tip to This bug report: Could not map a one-to-many relationship where the key is not the primary key.
mapping.HasMany(x => x.Children)
.Table("Child").KeyColumn("ParentReferenceId")
.PropertyRef("ReferenceId")
.Inverse()
.AsBag();
Theoretically, AsMap should work almost the same way, but for some reason that I'm not entirely clear on, it doesn't work for me. I'll explore that later, but I'm open to suggestions.