Entity Framework Core 6 many-to-many relationship navigation property exclusion - many-to-many

I have two entities linked that have a many-to-many relationship as shown here:
public class Product
{
//Omitted code...
public virtual ICollection<Ingredient> ingredients { get; set; }
}
public class Ingredient
{
// Omitted code...
public virtual ICollection<Product> products { get; set; }
}
My question is: I want to load only Product.ingredients navigation property, and I don't want to load the other side of the relation which is ingredient.Products. I want to keep the many-to-many relationship. How can I prevent the ingredient.Products navigation property from being loaded ?
Thanks in advance

Related

EF - how to prevent eager loading to load all nested entities

I've manay-to-many relationship between two entities: Categories <--> Items
public class CategoryMaster
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual List<SubCategoryMaster> SubCategories { get; set; }
public List<ItemMaster> Items { get; set; }
}
public class ItemMaster
{
public long Id { get; set; }
public string Name { get; set; }
public List<CategoryMaster> Categories { get; set; }
}
Whenever I try to explicit load related items to all/certain categories, it gives me
all related items
related categories to those items
related items to those categories and so on...nested/circular references
db.CategoryMaster
.Include(x=>x.Items)
.Include(x=>x.SubCategories.Select(y=>y.Items))
.ToList();
Hence results in below error while serializing it to JSON on *.cshtml with Json.Encode();
A circular reference was detected while serializing an object of type 'GoGreen.Data.Entities.SubCategoryMaster'.
Since I've disabled the lazy loading at property level, I'm not expecting it to load all nested entities(circular references) at any point of time. Is there a way to load all related level one records i.e. Categories and related items.
Related question - But Iodon't want to go with any of the two ways suggested.
NOTE : I'm more interested in knowing why EF behaves like this. It seems a bug to me.
First approach: you can add attribute above properties you don't want to exclude it from being serialized using [ScriptIgnore], you can create partial class and add your customization if your entities are auto generated
Second approach: Create a Model with only properties you need in your view and select only this model and set your properties
EFcontext.Tabel.include(x=>x...).Select(x=>new MyModel { ... });
One workaround, and please don't kill me :-) After object loading and before serializing, just set the loaded objects which are causing the circular reference to null. I tried it and worked like a charm.
use meta data redirection. figured I would help anyone who stumbled here.
[MetadataType(typeof(CategoryMasterMetadata))]
public partial class CategoryMaster
{
}
public class CategoryMasterMetadata
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
[JsonIgnore]
public virtual List<SubCategoryMaster> SubCategories { get; set; }
public List<ItemMaster> Items { get; set; }
}

Entity Framework Code First - Mapping entites from another database to include in model

I've been tasked with creating a sub application of an existing site. The sub application needs to make use of the users in the parent site but this is under a different database.
I'm using Entity Framework code first for the new site. However, I wish to create a mapping between the parent database user table and the new code first database.
Is this possible?
ParantDB.dbo.User
SubDB.dbo.Order
SubDB.dbo.OrderItems
public class Order
{
public int OrderId { get; set; }
public User Customer { get; set; } // Maintains a relationship user table
}
public class User
{
public int UserId { get; set; }
....
}
public class SubSiteContext : DbContext
{
public DbSet<Order> Orders { get; set; }
public DbSet<User> Users { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//???? I Presume I need to do the mapping here??
}
}
Context can be bound only to a single connection string = single database. The workaround for this cab be for example creating database view in your SubDB which will internally hide query to ParentDB.dbo.Users and map this view in the same way as you map tables.

EF Code First unidirectional One-To-Many with Data Annotations

Say I have the following POCO classes:
public class Parent
{
public int ID { get; set; }
}
public class Child
{
public int ID { get; set; }
public int MyParentID { get; set; }
[ForeignKey("MyParentID")]
public Parent MyParent { get; set; }
}
The Child.MyParent property maps to the Parent table with a one-to-many relationship, but I don't want the Parent class to be aware of the association (unidirectional). I can do this within the DbContext.OnModelCreating (or any of its equivalents) with the following:
modelBuilder.Entity<Child>()
.HasRequired(c => c.MyParent)
.WithMany()
.HasForeignKey(c => c.MyParentID);
But, I can't seem to find the same with data annotations. Is there such a thing? The ForeignKey annotation I am using seems to require bidirectionality, because it gives me the "Unable to determine the principal end of an association" exception until I add an ICollection<Child> property on the Parent class
UPDATE
This code should actually work as-is. The issue I was trying to isolate in my code didn't actually involve this setup. I've posted a new question regarding my problem here.
public class Child
{
public int ID { get; set; }
[ForeignKey("Parent")]
public int ParentID { get; set; }
public Parent Parent { get; set; }
}
should work. Actually you don't need to do anything - neither in Fluent API nor with annotations - because EF conventions will exactly create the relationship automatically you have defined in Fluent API. The foreign key will be detected because it has the name pattern [Navigation property]Id, the relationship will be "required" because the FK is non-nullable and it will be one-to-many because you have a single reference (Parent) on one side and "many" on the other side is default if there is no corresponding navigation property.

Entity Framework 4.1 one to one relationship nullable

Hello everybody again,
I need some help in this logic for EF 4.1
I have one table with data for a customer. I have also another table with a survey i need to compile when needed.
So initally i could insert a new customer and after some days I'll fill the survey form. Then the relationship MUST be one-to-one and optional (just because this survey could never be compiled for a customer).
I digged in some examples online but i'm really stuck.
Thank you in advance.
Simply define your entities like:
public class Customer
{
public int Id { get; set; }
...
public virtual Survey Survey { get; set; }
}
public class Survey
{
[Key, ForeignKey("Customer")]
public int Id { get; set; }
public virtual Customer Customer { get; set; }
}
If you don't like data annotations remove them and place this into OnModelCreating in your context:
modelBuilder.Entity<Customer>()
.HasOptional(c => c.Survey)
.WithRequired(s => s.Customer);

Applying Domain Model on top of Linq2Sql entities

I am trying to practice the model first approach and I am putting together a domain model. My requirement is pretty simple: UserSession can have multiple ShoppingCartItems.
I should start off by saying that I am going to apply the domain model interfaces to Linq2Sql generated entities (using partial classes). My requirement translates into three database tables (UserSession, Product, ShoppingCartItem where ProductId and UserSessionId are foreign keys in the ShoppingCartItem table). Linq2Sql generates these entities for me. I know I shouldn't even be dealing with the database at this point but I think it is important to mention.
The aggregate root is UserSession as a ShoppingCartItem can not exist without a UserSession but I am unclear on the rest. What about Product? It is defiently an entity but should it be associated to ShoppingCartItem?
Here are a few suggestion (they might all be incorrect implementations):
public interface IUserSession {
public Guid Id { get; set; }
public IList<IShoppingCartItem> ShoppingCartItems{ get; set; }
}
public interface IShoppingCartItem {
public Guid UserSessionId { get; set; }
public int ProductId { get; set; }
}
Another one would be:
public interface IUserSession {
public Guid Id { get; set; }
public IList<IShoppingCartItem> ShoppingCartItems{ get; set; }
}
public interface IShoppingCartItem {
public Guid UserSessionId { get; set; }
public IProduct Product { get; set; }
}
A third one is:
public interface IUserSession {
public Guid Id { get; set; }
public IList<IShoppingCartItemColletion> ShoppingCartItems{ get; set; }
}
public interface IShoppingCartItemColletion {
public IUserSession UserSession { get; set; }
public IProduct Product { get; set; }
}
public interface IProduct {
public int ProductId { get; set; }
}
I have a feeling my mind is too tightly coupled with database models and tables which is making this hard to grasp. Anyone care to decouple?
Looks like you are on the right track. Half of the whole "doing DDD right" is having the right base classes. Have a look at this great DDD applied to C# resource:
http://dddpds.codeplex.com/
The source code is available and is very readable.
So, with regards to having ID in the model. The ID is a database thing and the usual approach is to keep all persistence out of the Model and restrict the model to the business logic. However, one normally makes an exception for the identifier and buries it in the Model base class like so:
public class ModelBase {
protected readonly object m_Key;
public ModelBase(object key) {
m_Key = key;
}
}
This key is used by your persistence layer to talk to the database and is opaque. It's considered quite OK to downcast the key to the required type, because you know what it is.
Also, the Domain Objects are pretty much on the bottom of your architecture stack (just above the Infrastructure layer). This means that you can make them concrete classes. You will not have multiple implementations of the domain models, so the interfaces are unnecessary, which is what Domain Driven Design is about - Domain first.
public Class UserSession : ModelBase {
public UserSession(Guid Id):base(Id) {}
public Guid Id { get{ return m_Key as Guid;} }
public IList<ShoppingCartItem> ShoppingCartItems{ get; set; }
}
public class ShoppingCartItem : ModelBase {
public ShoppingCartItem ():base(null) {}
public UserSession UserSession { get; set; }
public Product Product { get; set; }
}
Typical shopping cart or customer-order examples prefer making UserSession (or Order) the root of aggregate. Individual items should be children of this session/order. It is up you whether individual items in the cart should have a meaningful id. I would prefer no, since 5 widgets in the cart are indistinguishable from another 5 widgets. Hence, I would model cart items as a collection of value objects.
Common problem with shopping cart items is whether they should include price, or not. if you include price, you will have your cart independent from changes of product price. It is very desirable if you want to store you cart for historical reasons since it is valuable to know how much items in the cart cost according to price when they were bought, not according to current.
Product should form definitively an aggregate by itself. Period.
Now, I don't know if all of this is easily implementable in LINQ to SQL, but you can try.