Am I building the wrong entities in MVC? - c#

Goal. I have a "Gift" entity that describes what someone has to offer (babysitting, dog walking, etc) with a rating. And I want a "GiftCategory" entity that gives general category descriptive information (pets, sports, automotive, etc) for someone to search apon and then get all gift that have those categories. A "Gift" entity can have multiple "GiftCategory" entities associated with it. I want the ability to search for a category and pull out all "Gift" entities that have been created with those categories associated with them. Here is what I have so far but it doesn't seem to work with the entity first approach. Maybe I need another table that connects the two entities because currently the way the two tables are connected doesn't seem correct?
Gift entity:
public class Gift
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<GiftCategory> Categories { get; set; } // is this incorrect???
public int Rating { get; set; }
}
Category entity:
public class GiftCategory
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
The "GiftCategory" table that gets created creates a gift_id column that links the "GiftCategory" back to a gift (not what I want)!!!!
It seems like I would need to create a entity that connects the two entities? Something like:
public class ConnectGifts
{
public int Id { get; set; }
public string GiftId{ get; set; }
public string GiftCategoryID{ get; set; }
}
This way I can have multiple categories for a Gift, but the thing I don't understand is with entity first I really don't need this entity I just need what would be this table to get/query the "GiftCategory" entities for ids then get the gift ids to get all the gifts. So it seems like creating this entity is overkill? Is there a way to do it without creating a third table/entity ("ConnectGifts") with code first? Or am I not understanding that all entities are tables and all tables are entities? I'm also using linq-to-sql for all querying.

You're looking for a many-to-many relationship and can be defined as:
public class Gift
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<GiftCategory> Categories { get; set; } // is this incorrect???
public int Rating { get; set; }
}
public class GiftCategory
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<Gift> Gifts { get; set; }
}
So each has a collection of the other. Gift has many Categories and Category had many Gifts. You could use a bridge table like you've done with ConnectGifts but it's not necessary with EF. Using just Gift and GiftCategory, EF will actually create the bridge table for you.

Related

Is there any way to embed a class Element into a class Element in Entity Framework?

This is my code:
namespace MyProject.Models.Database
{
public class Recipe
{
public Guid Id { get; set; } = Guid.NewGuid();
public string Name { get; set; }
public string? Description { get; set; }
public string? Picture { get; set; }
public int Worktime { get; set; }
public int? Cooktime { get; set; }
public int Difficulty { get; set; }
public int Portions { get; set; }
public List<Ingredient> Ingredients { get; set; }
}
public class Ingredient
{
public Guid Id { get; set; } = Guid.NewGuid();
public Guid IngredientId { get; set; }
public int Qty { get; set; }
public string QtyUnit { get; set; }
}
}
I want the class "Recipe" to include many elements of type "Ingredient". Ive read stuff about One-to-One and Many-To-Many but i just dont get it...
any Ideas?
thx
One recipe can consist of many ingredients, one ingredient can also be in many recipes. This is a many-to-many relationship.
What you need to do is create a new class that contains Id, RecipeId, IngredientId.Name that class something like RecipeIngredient. When you are creating a DbSet<RecipeIngredient> in your db context, name your table RecipesIngredients.
What should be the data types of the properties in RecipeIngredient?
The Id property will be the primary key, you can decide the data type.
RecipeId will be a foreign key for the Recipe, so it needs the same data type as the primary key of the Recipe (in your case Guid).
IngredientId will be the foreign key for the Ingredient, so the data type will again be Guid in your case.
Note that instead of putting Id in your RecipeIngredient, you can create a composite key instead.
When should you do that? -> here
I suggest you learn about the different relationships and how to apply them using C# and Entity Framework Core -> here
Good luck on your learning journey! When you don't feel you understand a topic, don't worry and don't get discouraged, you just need more experience. Keep up the good work :)

How do I get the id of record in foreign key table using another column in that table in ASP.NET MVC?

I am new to ASP.NET MVC. Using Entity Framework 6, I am working on a project to store employee skills in a database. The user can enter a new skill into a list of skills. I would like to keep track of who added the new skill. I have a table of all of the employees.
These are the models for the two tables.
public partial class Skill
{
public int ID { get; set; }
public string Skill { get; set; }
[ScaffoldColumn(false)]
public int LastActionUserID { get; set; }
public virtual Employee Employees { get; set; }
}
public partial class Employee
{
public int ID { get; set; }
public string EmployeeLAN { get; set; }
public int LastActionUserID { get; set; }
public virtual Employee Employees { get; set; }//References itself for LastActionUserID
public virtual ICollection<Skill> Skills{ get; set; } //Omitted in initial question
}
There is a 1 to Many mapping of Employee to Skill. I can get the current user's EmployeeLAN but how do I get the id of that Employee record to put into the Skill table automatically when then new skill is created? Must I convert the table to an enumerable object and use SingleOrDefault or LINQ? Or is there an easier way using EF6? Also, setting this automatically when a new skill is created would be done in the controller, correct?
You're on the right track and you should continue to use EF6.
The Employee class should have a Skills list. That way you can call myEmployee.Skills and have a list of all the skills available.
public partial class Employee
{
public int ID { get; set; }
public string EmployeeLAN { get; set; }
public int LastActionUserID { get; set; }
public virtual ICollection<Skill> Skills{ get; set; }
}
Also, setting this automatically when a new skill is created would be done in the controller, correct?
You'll need to add to the Skills list, call AddOrUpdate() to mark this as changed, then SaveChanges() to persist it to the database.
I recommend learning more from the MSDN docs and Julie Learman's
Entity Framework videos on Pluralsight

Entity Framework Code First "join table"

I am working with Entity Framework Code First.
I have an Entity Called Notes
I also have other Entities such as
BusinessPartners
Opportunities
WorkOrders
All of these entities may have notes.
What is the best way to model this
1.) in the notes table have optional foreign keys to Business partners, Opportunities, and workorders. Then just set the optional key to which the note is related
2.) have intermediate tables such as BusinessPartnerNotes, with two field BusinessPartnerId and NoteId
It should be mentioned that a note is never going to be related to two entities at the same time.
Any help or suggestions would be appreciated.
Given your description of the cardinalities, and assuming Notes for BusinessPartners have the same format of Notes for Opportunities, I'd go with the simplest approach (option 1. in your list).
class Note
{
public int Id { get; set; }
public string Content { get; set; }
}
class BusinessPartner
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Note> Notes { get; set; }
}
class Opportunity
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Note> Notes { get; set; }
}
Which should generate the following tables:
Notes
Id
Content
BusinessPartner_Id
Opportunity_Id
BusinessPartners
Id
Name
Opportunities
Id
Name

Entity Framework - Code First - Map results to Not Mapped properties

I have created these entities Product, Order, OrderedItem in EF using Code First.
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
[NotMapped]
public int IssuedQuantity { get; set; }
[NotMapped]
public int InhandQuantity { get; set; }
public virtual ICollection<OrderedItem> OrderedItems { get; set; }
...
}
public class Order
{
public int Id { get; set; }
public string ReferenceNumber { get; set; }
public virtual ICollection<OrderedItem> OrderedItems { get; set; }
...
}
public class OrderedItem
{
public int OrderId { get; set; }
public string ProductId { get; set; }
[ForeignKey("OrderId")]
public virtual Order Order { get; set; }
[ForeignKey("ProductId")]
public virtual Product Product { get; set; }
...
}
Now I want to get all products by passing current user id to a stored procedure. It will then return all products along with total product quantity currently in user's hand.
The problem is that EF is not mapping SP results back to Product entity for NotMapped properties. i.e. all properties in product entity have values but NotMapped properties are set to NULL even when I return their values from SP.
What I want to ask is that does EF support this kind of functionality? If yes then how?
NOTE I know about Computed Properties but that will create unneccessary columns in tables and I don't want that, since these properties are calculated at run-time.
NOTE I know that I don't need to create OrderedItem entity. But I am storing some other properties in it, which are removed here for brevity.
I'm quite sure that EF does not support dynamic mapping (you could try to change the mapping metadata but is not a clean way or delete the mapping cache but then EF will be very slow). In this case the razionale is that the entity are 2 different entities because they have different data. In your case probably the best thing is to do 2 entities the ProductWithQuantities that inherits from Product.
BTW Thinking about ERPs, the model of orders/wms usually is different. Products does not contain informations about QtyOnHand or sales/buy information. Usually is another object (Inventory?) that contains this informations.
I would create a View Model of the product with all the required properties and pass that to the view instead of the Product model. Then you are not constrained by the mappings of the Product model and you do not have to use the [NotMapped] Attribute on the fields.
[NotMapped]
public class ProductVM
{
public int Id { get; set; }
public string Name { get; set; }
public int IssuedQuantity { get; set; }
public int InhandQuantity { get; set; }
public virtual ICollection<OrderedItem> OrderedItems { get; set; }
...
}
I hope that helps.

Multiple tables containing one entity in Entity Framework

I am working on a system that sells products. This system has products, with subclasses for every producttype.
public abstract class Product
{
public int ProductId { get; set; }
public string naam { get; set; }
public string barcode { get; set; }
}
public class Card :Product
{
[Display(Name = "Cardnumber")]
public int nummer { get; set; }
public Kaliber kaliber { get; set; }
}
Furthermore, i want to keep a history of all the products i sold with all the data that was correct at that moment.
public class Transaction
{
public int transactionId { get; set; }
public Member member { get; set; }
public virtual ICollection<Product> producten { get; set; }
public double totaalprijs { get; set; }
public DateTime tijdstip { get; set; }
public string kantoorMedewerker { get; set; }
}
The problem is, that entity now makes a FK in Product to Transaction. That's not what i want. I want a seperate table for each of them; a Products table and a SoldProducts table.
I already tried this in my productContext:
public DbSet<Product> producten { get; set; }
public DbSet<Product> uitgifte_producten { get; set; }
That's not possible, because EF doesn't allow multiple object sets per type .
This seems like something trivial, but i can't figure it out.
Making two classes, one Product and one Soldproduct, with both of having subclasses of the producttypes, seems rather ugly. I tried it, but VS2012 complains that it can't converty Product to SoldProduct.
What seems to be a good idea to do this in C#, .net 4.0 and EF?
Why not just link to products from your transaction class using a basic many-to-many relationship?
Using EF Fluent API, you can add a config class with the following:
public class TransactionConfig : EntityTypeConfiguration<Transaction>
{
public TransactionConfig ()
{
this.HasMany(t => t.Products)
.WithMany()
.Map(x =>
{
x.MapLeftKey("TransactionId");
x.MapRightKey("ProductId");
x.ToTable("TransactionProducts");
});
}
}
Then, override the OnModelCreating function of you DbContext with:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new TransactionConfig());
}
I assume you are using EF Code First.
When you have a collection of products in your Transactions table, EF will take this to be a typical one to many relationship.
I would add a TransactionDetail table to which I would copy all the details I need from Product:
public class TransactionDetail{
public int TransactionId { get; set; }
public int ProductId { get; set; }
public string naam { get; set; }
public string barcode { get; set; }
}
Update in response to comment:
Still assuming you are using code-first. In your scenario, you could use the TransactionDetail class above as a base class then have more derived classes in respect to the types of products. You will be able to capture all the required details per product and you will only have one more extra table in your db.
I don't know of any way to do something like this in EF.
If you really want to keep all the product data for each transaction, I'd suggest creating product copies for every transaction and then storing them in the DB and referencing them from the transaction. You might also think about creating a self-reference on product, which could then point to the "actual product" for "transaction products".
Another approach I can think of is storing the product history instead of creating a copy of the product, i.e. creating product copies on product change instead of on transaction creation. This way, when creating a transaction you always link to the current version of your product.

Categories

Resources