Child objects in domain class - wcf-ria-services

I have a domain class like
public class Category
{
[Key]
public string IdCategory { get; set; }
public string Name { get; set; }
public List<Category> Children { get; set; }
public List<Product> Products { get; set; }
public Category()
{
Products = new List<Product>();
Children = new List<Category>();
}
}
In the generated code I find the products collection, but not the children collection. There are some restriction about using the same class? There is another way to modeling this relation without recurring to keys?

public class Category
{
[Key]
public string IdCategory { get; set; }
public string Name { get; set; }
public string IdFather { get; set; }
public List<Product> Products { get; set; }
[Include]
[Association("ParentChild", "IdCategory", "IdFather")]
public List<Category> Children { get; set; }
public Category()
{
Products = new List<Product>();
Children = new List<Category>();
}
}

Related

.NET Core: How to merge nested one-to-many relations in dto

How could merge nested child entity in parent?
I have these three entities:
public class Faculty
{
public Guid Id { get; set; }
public string Name { get; set; }
public ICollection<Group> Groups { get; set; }
}
public class Group
{
public Guid Id { get; set; }
public string Name { get; set; }
public ICollection<User> Users { get; set; }
}
public class User
{
public Guid Id { get; set; }
public string Name { get; set; }
}
Expected results in ResultDto is:
public class ResultDto
{
public Guid FacultyId { get; set; }
public string FacultyName { get; set; }
public ICollection<User> Users { get; set; }
}
You're looking for SelectMany:
var results = context.Faculties.Select(f => new ResultDto
{
FacultyId = f.Id,
FacultyName = f.Name,
Users = f.Groups.SelectMany(g => g.Users).ToList()
}
This will run in EF-core versions like 5 and 6, also in 3, but slightly less efficiently.

Alternative to List.Include in EF

I am having circular reference due to the EF code below. I have a Parent table with 2 childs and their grandchildren respectively. Is there any alternative to using Include, as I read something about Navigation property and it includes the parents in each of the child, causing the serialization having circular reference problem.
Error Message:
A circular reference was detected while serializing an object of type 'Product'.
This part is only to get retrieval and I don't need the parent reference back to each of the child. I debug inside and saw that inside each of the child, it has the parent reference back.
var query = db.Products.Include(c => c.ProductTriggers.Select(b => b.ProductTriggerItems))
.Include(d => d.ProductsExtra.Select(e => e.ProductAllotments.Select(m => m.ProductAllotmentDetails))).AsNoTracking();
return query.ToList();
Product Class
public partial class Product
{
public Product()
{
this.ProductExtras = new HashSet<ProductExtra>();
this.ProductTriggers = new HashSet<ProductTrigger>();
}
public int ProductID { get; set; }
public string ProductCode { get; set; }
public string ProductName { get; set; }
public virtual ICollection<ProductProduct> ProductExtras { get; set; }
public virtual ICollection<ProductTrigger> ProductTriggers { get; set; }
}
ProductExtra Class
public partial class ProductExtra
{
public ProductExtra()
{
this.ProductAllotments = new HashSet<ProductAllotment>();
}
public int ProductExtraID { get; set; }
public int ProductID { get; set; }
public virtual Product Product { get; set; }
public virtual ICollection<ProductAllotment> ProductAllotments { get; set; }
}
ProductAllotment Class
public partial class ProductAllotment
{
public ProductAllotment()
{
this.ProductAllotmentDetails = new HashSet<ProductAllotmentDetail>();
}
public int ProductAllotmentID { get; set; }
public int ProductExtraID { get; set; }
public virtual ProductExtra ProductExtra { get; set; }
public virtual ICollection<ProductAllotmentDetail> ProductAllotmentDetails { get; set; }
}
ProductTrigger Class
public partial class ProductTrigger
{
public ProductTrigger()
{
this.AddOnTriggerItems = new HashSet<ProductTriggerItem>();
}
public int ProductTriggerID { get; set; }
public int ProductID { get; set; }
public virtual Product Product { get; set; }
public virtual ICollection<ProductTriggerItem> ProductTriggerItems { get; set; }
}
ProductTriggerItem Class
public partial class ProductTriggerItem
{
public int ProductTriggerItemID { get; set; }
public int ProductTriggerID { get; set; }
public virtual ProductTrigger ProductTrigger { get; set; }
}

Returning Entity with its children

Hi I am trying to return all vehicles with their recorded mileage through an api using ASP.Net Core with the following code:
// GET: api/values
[HttpGet]
public IEnumerable<Vehicle> Get()
{
return _context.Vehicles.Include(m=>m.Mileages).ToList();
}
However this only returns the first vehicle with its mileages and not the others (there are five dummy vehicles in the db all with an initial mileage).
If I change the code to:
// GET: api/values
[HttpGet]
public IEnumerable<Vehicle> Get()
{
return _context.Vehicles.ToList();
}
it returns the full list of vehicles but no mileage.
My class files are:
public class Vehicle
{
public Vehicle()
{
Mileages = new List<Mileage>();
}
public int Id { get; set; }
public string Registration { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public Marked Marked { get; set; }
public ICollection<Mileage> Mileages { get; set; }
}
and
public class Mileage
{
public int Id { get; set; }
public DateTime MileageDate { get; set; }
public string RecordedMileage { get; set; }
//Navigation Properties
public int VehicleId { get; set; }
public Vehicle Vehicle { get; set; }
}
thanks for looking!
Tuppers
you can have them auto-load (lazy loading) using proxies... but for that, your foreign entities and collections must be marked virtual in your POCOs:
public class Mileage
{
public int Id { get; set; }
public DateTime MileageDate { get; set; }
public string RecordedMileage { get; set; }
//Navigation Properties
public int VehicleId { get; set; }
public virtual Vehicle Vehicle { get; set; }
}
public class Vehicle
{
public Vehicle()
{
Mileages = new List<Mileage>();
}
public int Id { get; set; }
public string Registration { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public Marked Marked { get; set; }
public virtual ICollection<Mileage> Mileages { get; set; }
}
The proxy creation and lazy loading turned on, but that's the default in EF6.
https://msdn.microsoft.com/en-us/data/jj574232.aspx
Let me know if this works.
Well after a lot of searching I managed to find a solution. I used the following:
[HttpGet]
public IEnumerable<VehicleDto> Get()
{
var query = _context.Vehicles.Select(v => new VehicleDto
{
Registration = v.Registration,
Make = v.Make,
Model = v.Model,
Marked = v.Marked,
Mileages = v.Mileages.Select(m => new MileageDto
{
MileageDate = m.MileageDate,
RecordedMileage = m.RecordedMileage
})
.ToList(),
})
.ToList();
return (IEnumerable<VehicleDto>) query.AsEnumerable();
this doesn't seem to be the most elegant way of doing this, if anyone could offer any advice but it does return what is required.
The DTO's look like:
public class VehicleDto
{
public string Registration { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public Marked Marked { get; set; }
public ICollection<MileageDto> Mileages { get; set; }
}
and
public class MileageDto
{
public DateTime MileageDate { get; set; }
public string RecordedMileage { get; set; }
}
Thanks for taking the time to look at this
Tuppers

ViewModel To Model Use ExpressMapper List<object> to List<Model> as Field

My Model Is :
public class Product
{
public int id { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public ICollection<Tag> Tags { get; set; }
}
public class Tag
{
public int id { get; set; }
public string Name { get; set; }
public int ProductId { get; set; }
[ForeignKey("ProductId")]
public virtual Product Product { get; set; }
}
And View Model Is :
public class ProductViewModel
{
public int id { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public List<string> Tags { get; set; }
}
im using ExpressMapper To Mapping.
could it be map productviewModel List Tags To public ICollection Tags?
You can register your mappings like that:
Mapper.RegisterCustom<Tag, string>((tag) => tag.Name);
Mapper.Register<Product, ProductViewModel>();
Mapper.Compile();
Here is working example: https://dotnetfiddle.net/2r7l4z

The Entity Framework created own columns for foreign keys

The Entity Framework ignores my foreign keys and creates own. How I can solve this problem?
I have few classes:
[Table("Entity")]
public class Entity
{
public Entity()
{
HeavyEntities = new List<HeavyEntity>();
}
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int EntityId { get; set; }
public string Name { get; set; }
public ICollection<HeavyEntity> HeavyEntities { get; set; }
}
[Table("HeavyEntity")]
public class HeavyEntity
{
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int EntityHeavyId { get; set; }
public int EntityId { get; set; }
public virtual Entity Entity { get; set; }
public int? TargetEntityId { get; set; }
public virtual Entity TargetEntity { get; set; }
public Relation Relation { get; set; }
}
[Table("Tech")]
public class Tech : Entity
{
public string Status { get; set; }
}
[Table("Company")]
public class Company : Entity
{
public string Country { get; set; }
}
Create and save entities:
var (context = new MyDbContex())
{
var tech = new Tech
{
Name = "Tech1",
Status = "New",
};
var company = new Company
{
Name = "Company1",
Country = "Ukraine"
};
tech.HeavyEntities.Add(new HeavyEntity
{
Relation = Relation.AsParent,
TargetEntity = company,
});
context.Techs.Add(tech);
context.Companies.Add(company);
context.SaveChanges();
}
For this classes Entity Framework creates the following table (HeavyEntity):
How I can map foreign keys to my fields?
SOLVED:
[Table("Entity")]
public class Entity
{
public Entity()
{
HeavyEntities = new List<HeavyEntity>();
}
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int EntityId { get; set; }
public string Name { get; set; }
[InverseProperty("Entity")]
public ICollection<HeavyEntity> HeavyEntities { get; set; }
}
[Table("HeavyEntity")]
public class HeavyEntity
{
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int EntityHeavyId { get; set; }
[ForeignKey("EntityId")]
public int EntityId { get; set; }
public virtual Entity Entity { get; set; }
[ForeignKey("TargetEntityId")]
public int? TargetEntityId { get; set; }
public virtual Entity TargetEntity { get; set; }
public Relation Relation { get; set; }
}
Add the ForeignKey attribute.
see https://msdn.microsoft.com/en-us/data/jj591583#Relationships
[Table("HeavyEntity")]
public class HeavyEntity
{
[Key, DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int EntityHeavyId { get; set; }
public int EntityId { get; set; }
public virtual Entity Entity { get; set; }
public int? TargetEntityId { get; set; }
[ForeignKey("TargetEntityId")] // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<
public virtual Entity TargetEntity { get; set; }
public Relation Relation { get; set; }
}