Fluent nHIbernate - Map a referenced / embedded class to same table as parent - fluent-nhibernate

I have a flat view that consists of columns such as:
ResultID
ResultName
ResultTime
DisciplineCode
DisciplineName
DateModified
etc...
I have a Result class that currently matches the above schema (flat)
public class Result
{
public virtual string ResultID { get; set; }
public virtual string ResultName { get; set; }
public virtual decimal ResultTime { get; set; }
public virtual string DisciplineCode { get; set; }
public virtual string DisciplineName { get; set; }
public virtual DateTime DateModified { get; set; }
}
What I'd like, is to separate my Discipline properties into their own class like this:
public class Discipline
{
public virtual string DisciplineCode { get; set; }
public virtual string DisciplineName { get; set; }
}
And then change my Result class to:
public class Result
{
public virtual string ResultID { get; set; }
public virtual string ResultName { get; set; }
public virtual decimal ResultTime { get; set; }
public virtual Discipline Discipline { get; set; }
public virtual DateTime DateModified { get; set; }
}
So that the Discipline is embedded as a class.
The details come from the same table (or in my case, normalized view)
How can I map this with fluent nHibernate
I've looked at References, but not sure if that's right?

Component sorted this.
Didn't realize I'd actually asked this question already a few days ago (in a different form)
See my answer here - https://stackoverflow.com/a/11397884/131809

Related

Doubts about EF Core 2.1 Relations

I am working on Entity Framework Core Code First approach and ASP.Net Core 2.1 making 3 tables:
Person class
public class Person
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public PeopleProfessions PeopleProfessions { get; set; }
}
Professions' class
public class Profession
{
public string Id { get; set; }
public string Name{ get; set; }
public PeopleProfessions PeopleProfessions { get; set; }
}
peopleprofessions' class
public class peopleprofessions
{
[ForeignKey("PersonId ")]
public string PersonId { get; set; }
public ICollection<Person> People { get; set; }
[ForeignKey("ProfessionId")]
public string ProfessionId{ get; set; }
public ICollection<Profession> Professions { get; set; }
}
On my Context:
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<peopleprofessions>().HasKey(up => new { up.PersonId, up.ProfessionId });
}
Bearing this in mind:
People can have multiple professions.
The professions table is only for reading stored data like "Accountant".
I have doubts about how I can make table 3 only contain the foreigners and that it can meet the needs that I just mentioned.
I have tried to make the relationship appropriately but I also noticed that in tables 1 and 2 it requests both Id of the table people's professions.
I don't know if I am lost or if I am looking wrong or if there is an alternative to that situation. Thanks for any help you can give me.
You have the use of Collections on the navigation items a bit backwards. For your primary entities (Person and Profession), they should have collections, since it's one-to-many. But for the PeopleProfessions, each record is a single link to a specific entity, so no collection there just a direct object reference.
public class Person
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<PeopleProfessions> PeopleProfessions { get; set; }
}
public class Profession
{
public string Id { get; set; }
public string Name{ get; set; }
public ICollection<PeopleProfessions> PeopleProfessions { get; set; }
}
public class PeopleProfessions
{
public string PersonId { get; set; }
public Person Person { get; set; }
public string ProfessionId { get; set; }
public Profession Profession { get; set; }
}
You can, but don't need to specify a ForeignKey attribute because you are following EFs naming conventions(it will figure it out for you). Your OnModelCreating looks correct for the composite key.
You may want to consider removing the plural from PeopleProfessions (just call the class PeopleProfession) since one instance represents a single People-Profession relationship. I typically do this and but the navigation name in the entities remains plural, since it can represent more than one, i.e.
public ICollection<PeopleProfession> PeopleProfessions { get; set; }

EF Code First not setting foreign key in one to one relationship

So I'm trying to create a simple Product-Preview 1 to 1 relationship as follows:
public class Product : BaseEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public string name { get; set; }
public virtual EPS eps { get; set; }
public virtual Preview preview { get; set; }
[ForeignKey("userId")]
public virtual User user { get; set; }
public Guid userId { get; set; }
}
and
public class Preview : BaseEntity
{
[Key,ForeignKey("Product")]
public Guid Id { get; set; }
public string imagePath { get; set; }
public double width { get; set; }
public double height { get; set; }
public virtual List<TextPreview> Texts { get; set; }
public virtual List<ImagePlaceHolder> ImagePlaceHolders { get; set; }
[ForeignKey("ProductId")]
public virtual Product Product { get; set; }
public virtual Guid ProductId { get; set; }
}
I was expecting to have a foreign key in the Previews table that would point to a Product
but after running the migration I just get it as regular field
What I'm I doing wrong?
You almost have it you just missed one piece of the puzzle ...
[ForeignKey("ProductId")]
public virtual Product Product { get; set; }
You also need to add ...
public Guid ProductId { get; set; }
to the preview object.
It's also worth noting that the ForeignKey attrib can be put on either property, and the string must refer to the other one of the pair.
As it's currently written you are trying to make the Id property specify the value for both the primary key and the foreign key on the tables in question.
So your final code might look something like ...
public class Product : BaseEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
[ForeignKey("User")]
public Guid UserId { get; set; }
public string name { get; set; }
public virtual EPS eps { get; set; }
public virtual Preview preview { get; set; }
public virtual User user { get; set; }
}
and
public class Preview : BaseEntity
{
[Key]
public Guid Id { get; set; }
[ForeignKey("Product")]
public Guid ProductId { get; set; }
public string imagePath { get; set; }
public double width { get; set; }
public double height { get; set; }
public virtual List<TextPreview> Texts { get; set; }
public virtual List<ImagePlaceHolder> ImagePlaceHolders { get; set; }
public virtual Product Product { get; set; }
}
As a side note I would also recommend against using concrete collection types like List<T> instead use something like IList<T> or ICollection<T> it promotes better code reuse and extensibility.

Fluent Nhibernate - One to Many Mapping - Child of same type as Parent

I have a class defined as:
public class ReportClient
{
public virtual int? Id { get; set; }
public virtual long? ClientId { get; set; }
public virtual string Name { get; set; }
public virtual string EmailAddress { get; set; }
public virtual string AdditionalEmailAddress { get; set; }
public virtual List<ReportClient> ChildClients { get; set; }
}
As you can see ChildClients are of same type as Parent.
Please guide me how can I map 'ChildClients' so for each ChildClient in List<ReportClient> ChildClients there is a new table record with a column 'ParentId' being set for this record ( having ParentId = Id)
Please guide.
Thank you!
I don't have the enviroment to test, but this should work, try swapping the column names if it doesn't.
HasManyToMany(x => x.ChildClients)
.ParentKeyColumn("ParentId")
.ChildKeyColumn("Id")

Fluent NHibernate mappings for localization

I am trying to build a Database from NHibernate mappings and have run into a problem.
I have many classes with localized string values:
public class MyClass1 {
public virtual int Id { get; set; }
public virtual ShortString Name { get; set; }
public virtual LongString Description { get; set; }
}
public class MyClass2 {
public virtual int Id { get; set; }
public virtual ShortString Name { get; set; }
public virtual LongString Description { get; set; }
}
and Languages like
public class Language {
public virtual string Code { get; set }
public virtual string Name { get; set }
}
My ShortString and LongString classes both look the same:
public class ShortString {
public virtual int Id { get; set; }
public virtual IDictionary<Language, string> Values { get; set; }
}
What I want to achieve are two tables (ShortString and LongString) looking like this:
TABLE ShortString
-----------------
Id (int)
LanguageCode (nvarchar(8))
Value (nvarchar(256)) (or ntext for the LongString Table)
...with Id AND LanguageCode as primary keys and a ForeignKey to the Language Table.
And in the MyClass1 and MyClass2 tables, I want to have NameId (int) and DescriptionId (int) columns mapped to ShortString and LongString tables respectively.
I am totally stuck. How can I achieve this?
Maybe you could ditch short and long string altogether
public class MyClass1 {
public virtual int Id { get; set; }
public virtual IDictionary<Language, string> Name { get; set; }
public virtual IDictionary<Language, string> Description { get; set; }
}
public class MyClass2 {
public virtual int Id { get; set; }
public virtual IDictionary<Language, string> Name { get; set; }
public virtual IDictionary<Language, string> Description { get; set; }
}
and use the folling Mapping
public class MyClass1Map : ClassMap<MyClass1>
{
public MyClass1Map()
{
[...]
HasMany(mc => mc.Name)
.Table("ShortString")
.KeyColumn("id")
.AsEntityMap("language_id")
.Element("value")
HasMany(mc => mc.Description)
.Table("LongString")
.KeyColumn("id")
.AsEntityMap("language_id")
.Element("value", e => e.Length(1000))
}
}
I cant test it right now so there might be tweaking nessesary

NHibernate Left Outer Join SubClass

I have 2 entities products and images. Not all images are product images, and images are a sub class of a file below are my entities. I need to find all of the images that are not associated to a product. I'm new to retrieval of entities and have tried numerous approaches. Any ideas or links would be greatly appreciated.
public class File
{
#region Feilds
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual Enumerations.File.FileType Type { get; set; }
public virtual string Extension { get; set; }
public virtual string Path { get; set; }
public virtual DateTime DateCreated { get; set; }
public virtual DateTime DateModified { get; set; }
#endregion
}
public class Image : File
{
#region Fields
public virtual string ImageName { get; set; }
public virtual string Description { get; set; }
public virtual bool Active { get; set; }
public virtual DateTime DateTaken { get; set; }
#endregion
}
public class Product
{
#region Properties
public virtual int Id { get; set; }
public virtual string Name { get; set; }
public virtual string Description { get; set; }
public virtual decimal Price { get; set; }
public virtual decimal Weight { get; set; }
public virtual bool IsDigital { get; set; }
public virtual DateTime DateCreated { get; set; }
public virtual IList<Category> ProductCategories { get; set; }
public virtual IList<ProductAttribute> ProductAttributes { get; set; }
public virtual IList<Image> ProductImages { get; set; }
#endregion
}
You can use a Critiria not exists subquery...
IList<Image> images = session.CreateCriteria<Image>("img")
.Add(Expression.Not(Subqueries.Exists(DetachedCriteria.For<ProductImageLink>("pil")
.SetProjection(Projections.Constant(1))
.Add(Expression.EqProperty("img.image_id", "pil.image_id")))))
.List<Image>();
Where ProductImageLink is the association table.
Should result in a query like...
select ... from image img where not exists(select 1 from productimagelink pil where img.image_id = pil.image_id);