Multiple Many-to-Many relationsship Entity Framework - c#

The main goal is the ability to have a many to many relationship between the table Mucle and Exercise. I want an Exercise to have both a primary and a secodary muscle group.
Is it possible to have two icollections in one model and only one in the other?
If someone could help with the "fluent configuration" as well, I would appreciate it!
Here is the code I have got right now.
public class Muscle
{
public int MuscleID { get; set; }
public bool IsFront { get; set; }
public string Name { get; set; }
public virtual ICollection<Exercise> Exercises { get; set; }
}
public class Exercise
{
public int ExerciseID { get; set; }
// ExerciseCategory
public int ExerciseCategoryID { get; set; }
public DateTime CreationDate { get; set; }
public string Description { get; set; }
public string Name { get; set; }
public virtual ExerciseCategory ExerciseCategory { get; set; }
public virtual ICollection<Muscle> Muscles { get; set; }
public virtual ICollection<Muscle> MusclesSecondary { get; set; }
}

No way to map the model you described.
To map your model (2 n-m relationship) you would need a Junction table with a discriminator and you can't do it with EF.
You have several way to change your model to make it work with EF
You create a model (a class) for the Junction table and insert a discriminator in it. Your model changes (and I think that the new model is less clear)
Why is there a Muscles and MusclesSecondary? Can it be discriminated with an attribute of Muscle? In this case you can have the attribute in Muscle and remove Exercise.MusclesSecondary Then you have only an n-m relationship that EF handles with a Junction table.
If you want this model you can add 2 collections to Muscle (for example ExcercisesMuscle and ExercisesMusclesSecondary) and a 3rd not mapped collection where you have the content of ExcercisesMuscle and ExercisesMusclesSecondary toghether. About the ExcercisesMuscle and ExercisesMusclesSecondary they can be observable collections so you can cache the content of Exercises collection in an efficient way.

Related

Would the Entity Framework's navigational properties work if I drop foreign key constraints from the database?

As you know that developers mostly mock the relationship between tables instead of using physical relationships between table (yeah, the line drawn from one table to another if you put a foreign key constraint on the column).
But I believe that Entity Framework doesn't work properly if physical relationships aren't there for navigational properties.
So, is there any way around?
My classes:
public class Phones
{
public int ID { get; set; }
public string Model { get; set; }
public string Manufacturer { get; set; }
public List<Users> Users { get; set; }
}
public class Sims
{
public int ID { get; set; }
public string Code { get; set; }
}
This creates a 1-M relationship from User -> Sims.
But what if I drop the foreign key constraint and leave it as it is, how will the navigational properties work then?
At this case better to remove references from both classes and handle relations manually outside of these classes:
public class Sims
{
public int ID { get; set; }
public string Code { get; set; }
//public User User { get; set; }
public int UserID { get; set; }
}

Modeling a one-to many relationship- Model vs ViewModel

I am currently trying to model an object class with a one-to-many relationship with another object in Model-First MVC- a "Contact" object that includes, among other things, a list of (references to?) one or more "Interests", chosen upon creation of a Contact from the full database list of Interests. It is my understanding that one uses a ViewModel to accommodate such a relationship, but I think I am misunderstanding what does or does not go in the model vs the viewModel.
At present, I have a Contacts model:
public class Contact
{
public int Id { get; set; }
public string Email { get; set; }
public virtual List<Interest> Interests { get; set; }
public List<int> InterestIds { get; set; }
}
An Interest model:
public class Interest
{
public int Id { get; set; }
public string Name { get; set; }
}
A Contact viewModel:
public class ContactViewModel
{
public int Id { get; set; }
public string Email { get; set; }
public List<int> InterestIds { get; set; }
public List<InterestViewModel> Interests { get; set; }
}
And an Interest viewModel
public class ContactViewModel
{
public int Id { get; set; }
public string Email { get; set; }
public List<int> InterestIds { get; set; }
public List<InterestViewModel> Interests { get; set; }
}
But I'm getting conflicted accounts of what goes where.
In short, I intend the end result that I should be able to choose one or more Interests (preferably with a series of checkboxes) from the Create view to be stored in the new Contact, and then from the Index view be able to filter the table of Contacts by which Interests they do or do not have. I have logic planned out for most of that already, but for the time being how should I design my Models vs my ViewModels in order to best accommodate this vision?
your Contact entity has a logical error, you should remove InterestIds property from Contact entity and add a property with name ContactId to your Interest entity. it provides foreign key for contact(one to many relation from Contact to Interest). however if ViewModel is equals to the Model, so you don't need any ViewModel.

Link Tables with Properties in EF6 Code First

I currently have a situation with code first EF6 where I need to create a many-to-many mapping (easy enough) however the generated relationship table needs to contain properties of its own. Here's a simplified example of what I have:
public class Journey : Entity
{
public string Name { get; set; }
public DateTime Start { get; set; }
public virtual ICollection<Point> Points { get; set; }
}
public class Point : Entity
{
public DbGeography GeoLocation { get; set; }
public string Name { get; set; }
public virtual ICollection<Journey> Journeys { get; set; }
}
The "Entity" class basically contains the primary key.
This would of course create a relationship table with foreign keys for the "Point" and "Journey" table primary keys. Great, but what if I want to add properties to that link table? Such as a DateTime property called ArrivalDate which holds the time of arrival at that point.
You could argue that I can add that property to the "Point" class but I want this table to hold a list of all physical points used in my application, without duplicates (a single point could be used in multiple journeys, each with different arrival dates). Therefor I need to hold this property elsewhere, the link table would be ideal here.
The only solution I can think of would be to create an actual relationship class:
public class JourneyPoint : Entity
{
public int JourneyId { get; set; }
public int PointId { get; set; }
public DateTime ArrivalTime { get; set; }
public virtual Journey Journey { get; set; }
public virtual Point Point { get; set; }
}
And then modify my Journey and Point classes to have a one-to-many relationship with the JourneyPoint class. However this just adds complication and isn't particularly semantic:
...
Journey myJourney = aMethodToGetMyJourney();
Point firstPoint = myJourney.JourneyPoints[0].Point.
...
That doesn't seems to make much sense and could confuse other developers. Is what I'm asking for possible at all?

EF Code first - Lazy Loading How to set up and access the joining table

public class Product
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public bool IsInStock { get; set; }
public string ImageUrl { get; set; }
public List<ProductOption> ProductOptions { get; set; }
public virtual Category Category { get; set; }
}
public class ProductOption
{
[Key]
public int Id { get; set; }
public string ProductOptionName { get; set; }
public string ProductOptionDescription { get; set; }
}
Now I know when your using Code First EF, so that the tables are created correctly. You need to do something like this.
modelBuilder.Entity<Product>().HasMany(p => p.ProductOptions).WithMany().Map(m =>
{
m.MapLeftKey("ProductId").MapRightKey("ProductOptionId").ToTable("SelectedProductOptionsInOrderedItem");
});
So....
Does this mean that if I do something like Product.ProductOptions I will be able to access all associated productoptions.
Is this the best way to set it up, or is there another way?
To enable lazy load and EF can create derived proxy types for your collection, that property should be declared this way:
public virtual ICollection<ProductOptions> ProductOptions { get; set; }
That should be enought. Other aspect is the mapping approach that you use. You choose fluent api, i prefer mapping by convention, but that is a matter of personal taste anyway.
Ok, Mapping by Conventions:
Is the ability of EF that from the name of entities and their properties along with their types, to map our model with the underlying data without providing any other information.
for example
public class Customer {
public long CustomerID {get; September;}
public string CustomerName {get; September;}
public Employee AssignedTo {get; September;}
}
With the previous model EF will map database with a table named Customer with:
. CustomerID bigint primary key column
. CustomerName nvarchar column
. Customer_EmployeeID foreign key to Employee table, with the datatype Corresponding to EmployeeID in that table.
You can read more Here

How to infer relationships and cardinality from a database when generating code from the tables?

I'm working on generating code (models) from my database. I'm not sure how to, if possible, setup my database to create a relationship including cardinality. Is this something that can be done, or am I stuck with simply generating models that match a table without relationships or cardinality because I did a data-first design?
Oh, and in case I'm using the incorrect term, cardinality is the type of relationship (one-to-one, one-to-many, many-to-many). That way my models will generate with a reference to another model, or to an ICollection<T> of models.
For example:
public class OrderInformation
{
public virtual int OrderId { get; set; }
public virtual DateTime OrderDate { get; set; }
public virtual BillingInformation BillingInfo { get; set; }
public virtual Address DeliveryAddress { get; set; }
public virtual ICollection<ItemInformation> ShoppingCart { get; set; }
}

Categories