Fluent NHibernate: Map property without foreign key? - c#

I have these two classes:
public class Parent
{
public virtual string Name { get; set; }
public virtual string Family_id { get; set; }
}
public class Children
{
public virtual string Name { get; set; }
public virtual DateTime BirthDate { get; set; }
public virtual string Family_id { get; set; }
}
When I fetch a parent, I also want to fetch the oldest (ordered by BirthDate) children that has the same Family_id as the parent.
There is no foreign key between the parent and the children in the database.
(I do not want to use two different repositories, I want the functionality in the mappings)
Is property-ref something I can use?

One strategy would be to force an Eager Load on a Children collection and create another property to get the oldest child.
Property-Ref is used to join to another table using a column which is not the primary key.
public class Parent
{
public virtual int Id {get; set;}
public virtual string Name { get; set; }
public virtual string Family_id { get; set; }
public virtual Children OldestChild {
get {
return Children.OrderBy(x=>x.BirthDate).FirstOrDefault();
}}
public virtual IList<Children> Children {get; set;}
}
public class ParentMap : ClassMap<Parent>{
public ParentMap(){
Id(x=>x.Id);
Map(x=>x.Name);
HasMany(x=>x.Children).PropertyRef("Family_id").Fetch.Join();
}
}
Another possibility would be to add a column to the Parent table (OldestChild_FK) and then join in that row from the Children table.

I think what you want to do is create a property on the Parent called OldestChild or a list of Oldest Children and ignore that property and write some custom query (HQL or SQL) to return the results you want.
Here is a thread on ignoring properties in FluentNhibernate.

Related

Fluently with NHibernate: reference other row in table by "parent_id" but return actual entity, not the id?

I was wondering if this is possible with Fluently in NHibernate. The scenario:
I have an entity looking something like this:
public class PairedEntity
{
public virtual int Id { get; set; }
public virtual int ParentId { get; set; }
}
ParentId is mapped to other entity in the same table (it's a OneToOne mapping by id). Is it possible, to somehow make Fluently fetch paired entity as something like that:
public class PairedEntity
{
public virtual int Id { get; set; }
public virtual int ParentId { get; set; }
...
public UnitEntity ParentUnitEntity { get; set; } // <----
}
Basically what I want is to store in table the id of parent entity, and let Fluently fetch it for me as some kind of "shadow" property, loaded into ParentUnitEntity.

SQL result to complex object with children

We're looking for a more efficient way to build objects with full parent/child relationships than looping through the results of separate queries and assigning children to parents. It seems to be a big bottleneck in our code right now (we often need to do this with 1,000's to 1,000,000's of entities at a time.
Is there a way to use a query with db.Database.SqlQuery<Parent>("SELECT * FROM xyz) that returns parent/child/grandchildren relationships?
public class Parent
{
public int Id { get; set; }
public string Name { get; set; }
public List<Child> Children { get; set; }
}
public class Child
{
public int Id { get; set; }
public List<Grandchild> Grandchildren { get; set; }
}
public class Grandchild
{
public int Id { get; set; }
}
using EF you could do something like this
db.Parent.Include(e=> e.Child).Include(e=> e.Child.SelectMany(s=> s.Grandchild));
using SqlQuery you should ensure the SQL SELECT includes all the necessary columns, using the aliases when necessary in order to match object property names

Entity Framework Reverse Navigation

I have 2 simple tables Order and Order Type.
I want to know if there is a way to reverse navigate the entity, where I can select the ordertype entity and show all orders entities.
Yes. I assume an order has one order type.
public class Order
{
public virtual OrderType Type { get; set; }
}
public class OrderType
{
public virtual ICollection<Order> Orders { get; set; }
}
I made the navigation properties virtual to enable lazy loading. If you want to, you can also add the foreign key property: (assuming you use a long key)
public class Order
{
[ForeignKey("Type")]
public long TypeId{ get; set; } //Can also be nullable (long?) if you want
public virtual OrderType Type { get; set; }
}
public class OrderType
{
[Key]
public long Id { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}

Can't update child entity without going through parent in entity framework

I'm trying to update a child entity but there is a foreign key relationship that is created between the parent and the child. I've created a repository for the child entity and when I try to insert a child into the db without first pulling the parent the foreign key column is empty. Here is my scenario.
parent entity
public class YogaSpace
{
public int YogaSpaceId { get; set; }
//other members here
public virtual ICollection<YogaSpaceEvent> Events { get; set; }
}
child entity
public class YogaSpaceEvent
{
public int YogaSpaceEventId { get; set; }
public string Title { get; set; }
public DateTime DateTimeScheduled { get; set; }
public int AppointmentLength { get; set; }
public int StatusEnum { get; set; }
}
in the database table YogaSpaceEvent it creates a column called 'YogaSpace_YogaSpaceId' that hold the foreign key to the parents YogaSpace's id.
So now if I want to insert a new YogaSpaceEvent into the table directly using a newly created repo here.
//calling yogaspaceeventrepo to insert directly into child entity table
yogaSpaceEventRepository.Add(Convert.ToInt16(id), title, dateWithTime, Convert.ToInt16(duration));
yogaSpaceEventRepository.Save();
I don't have access, via c#, to add a value to 'YogaSpace_YogaSpaceId' so the column value is empty .
YogaSpaceEvent table
I have to go and use my parent entity 'YogaSpace' repository and fetch a 'YogaSpace' and then add a new 'YogaSpaceEvent' to it. It's like two more steps and another fetch from the db but it works.
Is there another way to insert the 'YogaSpaceEvent' directly into the table without having to go through the parent entity 'YogaSpace'? Is there another way I can use code first attributes to do this, even though there is a foreign key relationship?
public class YogaSpaceEvent
{
public int YogaSpaceEventId { get; set; }
public int YogaSpaceID { get; set;}
[ForeignKey("YogaSpaceID")]
public virtual YogaSpace YogaSpace {get; set;}
public string Title { get; set; }
public DateTime DateTimeScheduled { get; set; }
public int AppointmentLength { get; set; }
public int StatusEnum { get; set; }
}
Add a new property for the parent I'd and another property for the parent object. Mark the parent object as virtual and set the Foreign Key attribute
You can add the YogaSpace_YogaSpaceId property to YogaSpaceEvent so that you can manipulate the parent Id directly. Without mapping the foreign key, you'll have to fetch the parent entity.

How to make proper code-first relations

I'm fairly new to Entity Framework and feel more in control using the Code-First pattern rather than DB-First.
I was wondering what is more preferred when it comes to programmatically setting up ForeignKey relations between the entities.
Is it better to declare a FK_ property in the class which relates to the another class or is it better to declare an IEnumerable<> property in the class that gets related to?
public class IRelateToAnotherClass
{
...
public int FK_IGetRelatedToByAnotherClass_ID { get; set; }
}
or
public class IGetRelatedToByAnotherClass
{
...
public IEnumerable<IRelateToAnotherClass> RelatedTo { get; set; }
}
It all depends on what type of relationships you want between your entities (one-to-one, one-to-many, many-to-many); but, yes, you should declare foreign key properties. Check out this site for some examples.
Here's a one-to-many for your two classes:
public class IRelateToAnotherClass
{
public int Id { get; set; } // primary key
public virtual ICollection<IGetRelatedToByAnotherClass> IGetRelatedToByAnotherClasses { get; set; }
}
public class IGetRelatedToByAnotherClass
{
public int Id { get; set; } // primary key
public int IRelateToAnotherClassId { get; set; } // foreign key
public virtual IRelateToAnotherClass IRelateToAnotherClass { get; set; }
}
and with some Fluent API mapping:
modelBuilder.Entity<IGetRelatedToByAnotherClass>.HasRequired<IRelateToAnotherClass>(p => p.IRelateToAnotherClass).WithMany(p => p.IGetRelatedToByAnotherClasses).HasForeignKey(p => p.Id);
If I understand what you're asking correctly, you'd want both. You want an int FK property and an object property to use as the navigation property.
The end result would look something like this:
public class Employee
{
[Key]
public int EmployeeID { get; set; }
[ForeignKey("Store")]
public int StoreNumber { get; set; }
// Navigation Properties
public virtual Store Store { get; set; }
}
public class Store
{
[Key]
public int StoreNumber { get; set; }
// Navigation Properties
public virtual List<Employee> Employees { get; set; }
}
If you haven't already, take a look at navigation properties and lazy-loading. Note that EF is clever enough to figure out that an int StoreID property corresponds to an object Store property, but if they are named differently (such as without the ID suffix), you must use the [ForeignKey] annotation.

Categories