In my database I have tables tblCountry and tblCity. They are in 1:N relation. In my domain project I represent them by City and Country classes. Do I realy need CountryId in city class or just Country object?
City class:
public class City
{
public int CityId {get;set;}
public string Name {get;set;}
public double Longitude {get;set;}
public double Latitude {get;set;}
// This confuse me... is this modeled fine?
public int CountryId {get;set;}
public Country Country {get;set;}
}
Country class
public class Country
{
public int CountryId {get;set;}
public string Name {get;set;}
public IEnumerable<City> Cities {get;set;}
}
I populate city object something like this:
...
City myCity = GetCityByCityId(cityId);
myCity.Country = GetCountryByCountryId(myCity.CountryId);
return myCity;
...
Do I realy need CountryId in city class or just Country object?
The domain relationship is "City is located in the Country". The code should be based on domain as much as possible. Your City class will have a reference to the Country object:
class City {
private Country _country;
}
You should not have CountryId in the city because it is a persistence technicality. It should be handled by data access layer for you (ORM).
In this case Country is an aggregate root, it should be filled with all contained cities then you can simply get the country you want and find cities inside the aggregate root.
public class City
{
public int Id {get;set;}
public string Name {get;set;}
public double Longitude {get;set;}
public double Latitude {get;set;}
public City(Country country)
{ this.Country = country; }
}
public class Country
{
public int Id {get;set;}
public string Name {get;set;}
public IEnumerable<City> Cities {get;set;}
}
...
Country myCountry = repository.GetCountryByID(xyz); // return a country with all cities filled
City myCity = myCountry.Cities.First(c => c.Id = cityId);
return myCity;
...
Depending on the design if the City is the aggregate root then the design would be
public class City
{
public int Id {get;set;}
public string Name {get;set;}
public double Longitude {get;set;}
public double Latitude {get;set;}
public Country Country {get;set;}
}
public class Country
{
public int Id {get;set;}
public string Name {get;set;}
}
...
City myCity = repository.GetCityByID(xyz); // return a city with the associated country
Country myCountry = myCity.Country;
return myCity;
...
I prefer the following :
public class City
{
public int CityId {get;set;}
public string Name {get;set;}
public double Longitude {get;set;}
public double Latitude {get;set;}
public int CountryId {get;set;}
public Country Country {get;set;}
public void LoadCountryFromDB()
{
this.Country = GetCountryByCountryId(this.CountryId);
}
}
there is a lot of Data Layer Generation Tools and Models and Code Generation :
CSLAGen and MyGeneration which is one of ORM Tools (Object relation Mapping).
try To search for them .
Related
this is the entity
public class Order
{
public int Id {get;set;}
public int ProductName {get;set;}
}
public class BuyerBill
{
public BuyerBill()
{
BuyerBillItems = new List<BuyerBillItems>();
}
public int Id {get;set;}
public int OrderId {get;set;}
public int Status {get;set;}
public List<BuyerBillItems> BuyerBillItems { get; set; }
....
}
public class BuyerBillItems
{
public int Id {get;set;}
public int BuyerBillId {get;set;}
public int Fee {get;set;}
....
}
public class SellerBill
{
public SellerBill()
{
SellerBillItems= new List<SellerBillItems>();
}
public int Id {get;set;}
public int OrderId {get;set;}
public int Status {get;set;}
public List<SellerBillItems> SellerBillItems{ get; set; }
....
}
public class SellerBillItems
{
public int Id {get;set;}
public int SellerBillId {get;set;}
public int Fee {get;set;}
....
}
select sum(e2.Fee) from order e
join BuyerBill on e.Id=e1.OrderId
join BuyerBillItems e2 on e1.Id=e2.BuyerBillId
where e.Id=1
select sum(e2.Fee) from order e
join SellerBill on e.Id=e1.OrderId
join SellerBillItems e2 on e1.Id=e2.SellerBillId
where e.Id=1
There is only one row of order records in the SellerBill and SellerBill tables
BuyerBillItems and SellerBillItems tables may have many rows
I can only query with 2 T-SQL statements now, how can I query with one T-SQL?
My project is using EF CORE, so you guys better help me to query with EF CORE, thanks!
The result I want to get is
BuyerFee,SellerFee
200,100
Using LINQ, is it possible to combine properties from both an object and a nested collection of that object into a new object? So for each item in the nested collection, I want to create a new object that has the nested object information coupled with the parent object's info.
Using a sample scenario, I'm trying to do something like this:
Teachers.Select(Function(item) New TeacherRecord() With
{.TeacherId = item.Id,
.TeacherName = item.Name,
.StudentID = ? ,
.StudentName = ?}).ToList()
Sample Classes
Public Property Teachers as List(of Teacher)
Public Class Teacher
Public Property ID as Integer
Public Property Name as String
Public Property Room as String
Public Property Students as List(of Student)
End class
Public Class Student
Public Property ID as Integer
Public Property Name as String
End Class
Public Class TeacherRecord
Public Property TeacherId as Integer
Public Property TeacherName as String
Public Property StudentId as Integer
Public Property StudentName as String
End Class
You need to use SelectMany, I don't know much about VB but this is how you do it in C#:
List<TeacherRecord> records = teachers.SelectMany(t => t.Students, (t, s) =>
new TeacherRecord { TeacherId = t.ID,
TeacherName = t.Name,
StudentId = s.ID,
StudentName = s.Name }).ToList();
you will need to rethink your TeacherRecord relationship to a Teacher Or Student - now it is unclear, but generally you can combine then for your ViewData and code will look like this:
void Main(){
List<Teacher> teacher = new List<Teacher>();
List<Student> student = new List<Student>();
student.Add(new Student{ID=1,Name="Tom"});
student.Add(new Student{ID=2,Name="Jerry"});
teacher.Add(new Teacher{ID=1
,Name="John"
,Room = "Room A"
,Students = student});
var combined = (from t in teacher
select t).ToList();
}
// Define other methods and classes here
public class Teacher
{
public int ID { get; set; }
public string Name { get; set; }
public string Room { get; set; }
public List<Student> Students { get; set; }
}
public class Student
{
public int ID { get; set; }
public string Name { get; set; }
}
public class TeacherRecord
{
public int TeacherId { get; set; }
public string TeacherName { get; set; }
public int StudentId { get; set; }
public string StudentName { get; set; }
}
and result will be something like this:
Using NHibernate 2.1, I'm trying to project an entity and its child collection into a DTO. My entity looks like this..
public class Application
{
public int Id {get;set;}
public string Name {get;set;}
public List<ApplicationSetting> Settings {get;set;}
// A bunch of other properties that I don't want in the DTO
}
public class ApplicationSetting
{
public int Id {get;set;}
public string Name {get;set;}
public string Code {get;set;}
// A bunch of other properties that I don't want in the DTO
}
My DTO looks like this..
public ApplicationDto
{
public int Id {get;set;}
public string Name {get;set;}
public List<ApplicationSettingDto> Settings {get;set;}
}
public class ApplicationSettingDto
{
public int Id {get;set;}
public string Name {get;set;}
public string Code {get;set;}
}
My code to select JUST the Application and project it is this (using Nhibernate 2.1 and nhLambdaExtensions)
var applicationAlias = new Application();
var criteria = Session
.Add<Application>(a => a.Id == id);
int? Id = null;
string Name = null;
criteria
.SetProjection
(
Projections.Distinct(
Projections.ProjectionList()
.Add(LambdaProjection.Property<Application>(a => a.Id).As(() => Id))
.Add(LambdaProjection.Property<Application>(a => a.Name).As(() => Name))
)
);
criteria.SetResultTransformer(Transformers.AliasToBean(typeof(ApplicationDto)));
var contract = criteria.UniqueResult<ApplicationDto>();
My question is, how do I project just SOME of the properties from the ApplicationSettings entity to the ApplicationSettingsDto child collection?
I think you might need to do a MutiQuery and bring together the DTO parents and children yourself.
If I had a viewmodel that looked something like this
public class AddressViewModel
{
public int AddressID {get;set;}
public string Street {get;set;}
public string Town {get;set;}
public SelectList Countries { get; set; }
}
How would I go about populating this?
Would it be 2 queries to the database, 1 to populate the address info and another to return all countries into the SelectList?
I think so yes, maybe even cache it if the list values don't change.
I'm using Sharp Architecture and have a number of situations where Value Objects are used in an Entity. Here is an obvious simple example:
public class Person : Entity
{
protected Person(){}
public Person(string personName)
{
this.PersonName = personName;
}
public virtual string PersonName { get; protected set;}
public virtual StreetAddress MailingAddress { get; set; }
}
public class StreetAddress : ValueObject
{
protected StreetAddress(){}
public StreetAddress(string address1, string address2, string city, string state, string postalCode, string country )
{
this.Address1 = address1;
this.Address2 = address2;
this.City = city;
this.State = state;
this.PostalCode = postalCode;
this.Country = country;
}
public virtual string Address1 { get; protected set; }
public virtual string Address2 { get; protected set; }
public virtual string City { get; protected set; }
public virtual string State { get; protected set; }
public virtual string PostalCode { get; protected set; }
public virtual string Country { get; protected set; }
}
This of course throws: An association from the table Person refers to an unmapped class: Project.Domain.StreetAddress
because the the AutoPersistenceModelGenerator only includes classes with type IEntityWithTypedId<>. Its not clear how Sharp Architecture expects this common condition to be implemented. Does this have to be handled with a bazillion overrides?
You could change the GetSetup() method in AutoPersistenceModelGenerator to something like:
private Action<AutoMappingExpressions> GetSetup()
{
return c =>
{
c.IsComponentType = type => type.BaseType == typeof (ValueObject);
};
}
I'll try to get the blogpost I saw covering this posted for credit.
You would want to map this as a component. You can use the mapping overrides in Fluent NHibernate to accomplish this.
I agree with Alec. I would map this as a component.
For more information on that, see this SO question:
AutoMapping a Composite Element in Fluent Nhibernate
There, you'll also find info on how to map a collection of composite elements.