I'm working on a legacy MySql database and have the following entities:
public class Company
{
public int Id { get; set;}
public string Address { get; set; }
public string City { get; set; }
}
public class CompanyDepartment
{
public int Id { get; set;}
public string Address { get; set; }
public string City { get; set; }
}
The idea is that a company only use the department class if it has more than one department.
Right now I'm trying to make a company/department search, this means I need a list of all departments and therefore I need to "create" departments of all the companies that only has one department, and therefore don't have a entry in CompaynyDepartment.
To do this I was thinking of use components in fluent NHibernate, but I'm not sure I can join the real departments with the fake ones?
Is there a better approach to this problem? It's not an option to change the database structure.
I ended up changing the database structure
Related
I would like to use DTOs and AutoMapper to POST and PUT an entity containing a List of nested entities, having a hierarchy.
Sample :
A company has a list of employees. In this list of employees can have a manager which is also an employee of the same company.
public class Company {
public int Id { get; set; }
public List<Employee> Employees { get; set; }
}
public class Employee {
public int Id { get; set; }
public Company Company { get; set; }
public int CompanyId { get; set; }
public Employee Manager { get; set; }
public int? ManagerId { get; set; }
}
I'd like to create a DTO which is able to POST and UPDATE a Company creating/updating/removing and changing relations between employees.
How would you do knowing that some employees can have no Id yet because they are newly created but are parents of other employees ?
Thanks in advance for the help.
Precision : i use dot net core 2.2, Entity Framework Core and AutoMapper.
You can do this as below.
public class CompanyDto {
public int Id { get; set; }
//Below line cannot exist here, otherwise it will create circular references
//public List<Employee> Employees { get; set; }
}
public class EmployeeDto {
public int Id { get; set; }
public Company Company { get; set; }
public int CompanyId { get; set; }
public Employee Manager { get; set; }
public int? ManagerId { get; set; }
}
After this, you can create your mappings in automapper configuration for Company -> CompanyDto(and reverse map) and Employee to EmployeeDto(and reverse map).
Now, for handling the case of new manager with existing employee, you do either of the following in your repository(with entity objects, not DTO's)
Create a new employee and then update the existing employees with the newly generated employee id in your repository
Or, get all the employees you want to update in your repository(load in context), add the new employee in the context with EntityState.Added. Now, assign the manager of employees you have fetched with the reference of new employee and save your context
I'm having trouble getting the Fluent Nhibernate Automapper to create what I want. I have two entities, with a one-to-many relationship between them.
class Person
{
public string name;
IList<departments> worksIn;
}
class Department
{
public string name;
}
The above is obviously bare bones, but I would be expecting to generate the fleshed out schema of:
Person{id, name}
Department{id, name}
PersonDepartment{id(FK person), id(Fk Department)}
Unfortunately, I am instead getting:
Person{id, name}
Department{id, name, personid(FK)}
I don't want the FK for Person included on the department table, I want a separate join/lookup table (PersonDepartment above) which contains the primarykeys of both tables as a composite PK and also Fks.
I'm not sure if I am drawing up my initial classes wrong (perhaps should just be LIst workIn - representing ids, rather than List worksIn), or if I need to manually map this?
Can this be done?
The way the classes have been structured suggests a one-to-many relationship (and indeed that's how you describe it in your question), so it should not be a surprise that FNH opts to model the database relationship in that way.
It would be possible, as you suggest, to manually create a many-to-many table mapping. But, is this definitely what you want?
I tend to find that pure many-to-many relationships are quite rare, and there is usually a good case for introducing an intermediate entity and using two one-to-many relationships. This leaves open the possibility of adding extra information to the link (e.g. a person's "primary" department, or perhaps details of their office within each of their departments).
Some example "bare-bones" classes illustrating this kind of structure:
public class Person
{
public int Id { get; set;}
public string Name { get; set;}
public IList<PersonDepartment> Departments { get; set; }
}
public class PersonDepartment
{
public int Id { get; set; }
public Person Person { get; set; }
public Department Department { get; set; }
public bool IsPrimary { get; set; }
public string Office { get; set; }
}
public class Department
{
public int Id { get; set; }
public IList<PersonDepartment> Personnel { get; set; }
public string Name { get; set; }
}
I have a problem using QBE with NHibernate. I have a one-to-one relationship between a Person class and an Employee.
public class Person
{
public virtual Employee Employee { get; set; }
public virtual int Age { get; set; }
public virtual string Forename { get; set; }
public virtual string Surname { get; set; }
public virtual int PersonID { get; set; }
}
public class Employee
{
public virtual int PersonID { get; set; }
public virtual string PayRollNo { get; set; }
public virtual int Holidays { get; set; }
public virtual Person Person { get; set; }
}
As an example, I want to get all Employees where Employee.Forename="John" and Employee.Person.PayRollNo = "231A". I was wondering if I could use Query By Example to do this?
I have not been able to find a definitive "no" but I haven't been able to get this work. I've found that QBE is promising but unfortunately not very useful due to the following limitations:
Cannot query related objects.
Requires public parameterless constructor.
Initialized properties are included in query unless specifically excluded using ExcludeProeprty. For example, bool properties are restricted to false in the where clause, DateTime as DateTime.MinValue. This makes the query very brittle because class modifications may have bad side effects.
I'm using NHibernate in my web app and it is mapped with my database. I have a model, somthing like this:
public class Company {
public virtual string Name { get; set; }
public virtual IList<Employee> Employeers { get; set; }
}
public class Employee {
public virtual string Name { get; set; }
public virtual DateTime Birthday { get; set; }
/* other properties */
public virtual Company Company { get; set; }
}
PS: it's not real model but it works for my samples/doubts...
I'm using HQL to get my objects and I'd like to know if is there any way to:
1) Get a Company object and fill the Employeers Colletion with Top 10 Employeers Ordered by Birthday Desc ?
2) Is there any way to, when collection is filled, fill it with only some fields like Name and Birthday? I have a lot of properties that I won't use in my view. I can create a DTO for this but I don't know how to do!
Thanks
Persistent collections and entities represent the current state; they can't have just a part of that (think about it: if they did, how would NH track changes?)
So, in both cases, the answer is queries and DTOs. You can easily retrieve the data you need with HQL:
class EmployeeNameAndBirthDay
{
public string Name { get; set; }
public DateTime Birthday { get; set; }
}
public IList<EmployeeNameAndBirthDay> GetTopEmployees(Company company)
{
return session.CreateQuery(#"
select Name as Name,
Birthday as Birthday
from Employee
where Company = :company
order by Birthday desc
")
.SetParameter("company", company)
.SetMaxResults(10)
.SetResultTransformer(
Transformers.AliasToBean<EmployeeNameAndBirthDay>())
.List<EmployeeNameAndBirthDay>();
}
When automapping a joined subclass in fluent nhibernate, I can't figure out how to give the joined subclass a primary key.
public class Address:Entity {
public virtual string Address1 { get; set; }
public virtual string Address2 { get; set; }
public virtual string City { get; set; }
public virtual string State { get; set; }
public virtual string Zip { get; set; }
public virtual string Phone { get; set; }
public virtual string Fax { get; set; }
public virtual IList<Location> Locations { get; set; }
}
public class Location:Address {
public virtual Address BillingAddress { get; set; }
public virtual string OfficeHours { get; set; }
public virtual string PatientAgeRestrictions { get; set; }
public virtual bool WheelchairAccess { get; set; }
public virtual string ContactPerson { get; set; }
public virtual string ContactEmail { get; set; }
public virtual string ContactPhone { get; set; }
public virtual string ContactFax { get; set; }
public virtual string TaxId { get; set; }
}
I want Location to have it's own id "location_ id" with it's own sequence. Then I want that mapped to address through an address_id column.
Right now it's generating the location with "addressid" as the primary key, which isn't what I want. How do I change this with the automapping?
I'm not sure you have a joined-subclass relationship. That is, by definition a joined subclass has the same ID as its parent class. For example, you might have a Person entity stored in your database for generic "people" information like name/age/etc and then an Employee subclass entity which is stored in a different table and holds data like position, salary, and dates of employment. So an Employee is a subtype of Person and to get the full "Employee-Person" object, you must join the two tables on their primary keys (e.g. SELECT * FROM Employee INNER JOIN Person ON Employee.Employee_id = Person.Person_id).
Are you sure about your relational model here? Is Location truly a subtype of Address? Inferring a bit from your property names, it seems to me that this is not what you intend. It seems like you probably have a many-to-many between an Address and an Organization (that is, there may be many "organizations" at the same address and an "organization" may have many addresses), with a "contact person" for the organization at a specific address. In which case you should map "organization", "contact", and another entity that defines the relationship between Address and "organization".