master details entities, aggregate root - Abp Core - entity-framework

what is the best way to create parent-child entities
e.g
oreder-->details
recipe-->ingredients
car-->parts
the doc talks about "Agregate root" https://aspnetboilerplate.com/Pages/Documents/Entities#aggregateroot-class
Is there any example? does exist another way? any suggestion please?
isn't this enough?
order entity:
....
...
..
[ForeignKey("OrderId")]
public virtual ICollection<OrderDetail> Details { get; set; }
....
...

that's it!
public class Order : FullAuditedEntity
{
public virtual ICollection<OrderDetail> Details { get; set; }
}
public class OrderDetail : FullAuditedEntity
{
[ForeignKey("OrderId")]
public virtual Order Order { get; set; }
public int OrderId { get; set; }
}

Related

How can I add two property in my model in EF code first from one model?

I want to add two properties from the city model:
after migration this error shows up:
Unable to determine the relationship represented by navigation
'City.Orders' of type 'ICollection'. Either manually configure
the relationship, or ignore this property using the '[NotMapped]'
attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
here is my code :
public class Order
{
public virtual City FromCity { get; set; }
public virtual City ToCity { get; set; }
}
public class City
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}
I suppose your model is more complicated than just FromCity and ToCity because I don't think it's a good idea to store such information in a different table. Yet, You can use inheritance in this case.
The table-per-hierarchy (TPH) pattern is used by default to map the inheritance in EF. TPH stores the data for all types in the hierarchy in a single table.
However, for your scenario, you can have a base class that holds all related attributes.
public class CityBase
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
}
Then suppose you need two entities as per your scenario:
public class FromCity : CityBase
{
public virtual ICollection<Order> Orders { get; set; } = null!;
}
public class ToCity : CityBase
{
public virtual ICollection<Order> Orders { get; set; } = null!;
}
And the order entity:
public class Order
{
public int Id { get; set; }
public string OrderTitle { get; set; } = string.Empty;
public virtual FromCity FromCity { get; set; } = null!;
public virtual ToCity ToCity { get; set; } = null!;
}
This approach can solve your problem with a One-to-Many relationship between Orders and FromCity, ToCity as per below diagram:

Can't set the Relation between 2 DB Models

I Got This Issue:
I Have the Application User Class Like This
public class ApplicationUser : IdentityUser
{
public ROLES Role { get; set; }
public int? CompanyId { get; set; }
public int? AreaId { get; set; }
public string Document { get; set; }
public bool Enable { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
[ForeignKey("AreaId")]
public virtual Area Area { get; set; }
public virtual ICollection Measures { get; set; }
}
And I Got this another Model:
public class Area
{
public int AreaId { get; set; }
public string AreaName { get; set; }
public int CompanyId { get; set; }
public string UserId { get; set; }
[ForeignKey("CompanyId")]
public virtual Company Company { get; set; }
[Key, ForeignKey("UserId")]
public ApplicationUser ApplicationUser { get; set; }
}
And when i try to:
add-migration
the PM Console throws:
Unable to determine the principal end of an association between the types 'x.Models.ApplicationUser' and 'x.Models.Area'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
I have been trying all day but I can't find a way to tell the Entity Framework to recognize the relation.
Any ideas?
Thanks for reading
Add Attribute for AreaId in Area class
[Key]
public int AreaId { get; set; }
and if you want 1-1 relationship for ApplicationUser and Area update your code like
[Unique]
[ForeignKey("UserId")]
public ApplicationUser ApplicationUser { get; set; }
The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations
This Post give me the Answer I Need!!!
It's pretty hard to find...
So I let you the post here...
Thanks for all of your help!

Map many to many objects using Entity Framework

For example we have profile and organisation. Both have articles.
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
}
public class Profile
{
public int Id { get; set; }
public string Email { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
public class Organisation
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Article> Articles { get; set; }
}
In this way Article should have two kinds of parent so it should have something like parent type to be able to access a parent when you select articles directly.
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public int ParentId { get; set; }
public ArticleParentType Parent { get; set; }
}
Is it possible to map it using Entity Framework?
Is it a good idea to do it?
What is the best practice for storing this kind of data?
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public int ParentId { get; set; }
public ArticleParentType Parent { get; set; }
}
Is it possible to map it using Entity Framework?
Is it a good idea to do it?
Possible yes but not a good idea. The underlying Database can't use a foreign key for Parentid. It would be slow.
What is the best practice for storing this kind of data?
A simple approach, with 2 Nullable parents and without CascadeOnDelete:
public class Article
{
public int Id { get; set; }
public string Title { get; set; }
public virtual Profile Profile { get; set; }
public virtual Organisation Organisation { get; set; }
}
Alternatively you could use inheritance for Article, ie class OrganisationArticle : Article {}

Entity Framework Code-First treats my code as one to many , although I want it to be many to many relationship

I'm trying to make a database where one of the tables has a one to one relationship and a many to many relationship ... The database created seems to be working as one to one relationship only. here's my model:
public class Trip
{
public int ID { get; set; }
public virtual ICollection<Place> PassingBy { get; set; }
public Place Origin { get; set; }
public Place Destination { get; set; }
public DateTime Time { get; set; }
public int EmptySlots { get; set; }
public virtual ICollection<Person> Attendants { get; set; }
public string AccessKey { get; set; }
}
public class Person
{
public int ID { get; set; }
public string Username { get; set; }
public virtual ICollection<Trip> Trips { get; set; }
}
public class Place
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Trip> Trips { get; set; }
}
public class GARDB : DbContext
{
public DbSet<Trip> Trips { get; set; }
public DbSet<Person> Persons { get; set; }
public DbSet<Place> Places { get; set; }
}
Now, when I do add-migrations and update database. The database has a table called "PersonTrip" which is needed for the many to many relationship. But there is no table for "PlaceTrip" . After some trial and error. I found out it's because of these lines:
public Place Origin { get; set; }
public Place Destination { get; set; }
They cause the relation to be one to many. Non many to many as I want to to be. Is there a way to make the Place-Trip relation like the Person-Trip one but without removing those 2 lines.
Thanks!
EDIT: The Solution
I didn't make clear what I wanted. I wanted to make the line
public virtual ICollection<Place> PassingBy { get; set; }
to be mapped to the line
public virtual ICollection<Trip> Trips { get; set; }
in the Place class. The solution I got to from the answers was this:
replace :
public virtual ICollection<Place> PassingBy { get; set; }
with:
[InverseProperty("Trips")]
public virtual ICollection<Place> PassingBy { get; set; }
and replace :
public virtual ICollection<Trip> Trips { get; set; }
in the Place class with:
[InverseProperty("PassingBy")]
public virtual ICollection<Trip> Trips { get; set; }
and add this include at the top:
using System.ComponentModel.DataAnnotations.Schema;
What's confusing it, in effect, is that you have two ends for the relationship on Trip:
public Place Origin { get; set; }
public Place Destination { get; set; }
(which should also be virtual, BTW), and only one on Place:
public virtual ICollection<Trip> Trips { get; set; }
...so Entity Framework can't figure out which goes with what.
You need to add both a second navigation property to Place, and some data annotation attributes to tell Entity Framework how they relate to form the two halves of the many-to-many relationship. Omitting the other properties and the context for clarity, like this:
public class Trip
{
[InverseProperty ("AsOrigin")]
public virtual Place Origin { get; set; }
[InverseProperty ("AsDestination")]
public virtual Place Destination { get; set; }
}
public class Place
{
[InverseProperty ("Origin")]
public virtual ICollection<Trip> AsOrigin { get; set; }
[InverseProperty ("Destination")]
public virtual ICollection<Trip> AsDestination { get; set; }
}
If you need a single property on Place that gives you all trips that it's involved in, either as origin or destination, you can recreate it using the navigation properties like this:
[NotMapped]
public ICollection<Trip> Trips
{
get
{
return AsOrigin.Concat(AsDestination).Distinct();
}
}
I'm not a big fan of the relationships that you're creating here, but that's something for your DBA to chew on. In the meantime, if you want to do something like this, may I suggest utilizing the answer to this SO question which is trying to do something very similar. You would need to add a couple of more properties and set up foreign key relations between the tables, but it should work out just fine.

Mapping nested classes via Entity Framework

I have class with this definition :
public class WebSiteContent
{
public Guid Id { get; set; }
public About About { get; set; }
public Tips Tips { get; set; }
public Images Images { get; set; }
}
where my About and Tips and Images are look like this :
public class About
{
public Guid Id { get; set; }
public string Text { get; set; }
public string Addres { get; set; }
public int PhoneNumber { get; set; }
public int Mobile { get; set; }
}
and Tips :
public class Tips
{
public Guid Guid { get; set; }
public string Content { get; set; }
}
and Images :
public class Images
{
public Guid Id { get; set; }
public string Background { get; set; }
public string Logo { get; set; }
public About About { get; set; }
}
here i just want to use about and Images and tips as a helper class to just create a property and don't want to have about,Images or tips table in database !
Entity framework needs Id to map all of above classes , how can I do that ?
here i just want to use about and Images and tips as a helper class to
just create a property and don't want to have about,Images or tips
table in database
So you are looking for complex type. Mark your About, Tips and Images classes with [ComplexType] attribute.
Entity framework needs Id to map all of above classes , how can I do
that ?
EF only needs Id for entities. If you map them as complex types you will not need to use any Id.
Btw. if you don't want to have those classes and their properties in database at all you can use [NotMapped] attribute instead.