Non unique object nhibernate c# - c#

I am working with c # and nhibernate in mysql, I have a list that stores sell products which at some point may be the same but different price.
Product A - Price 3.00
Product A - Price Two: 2.50
when wanting to save it shows me the following, which I'm sure is that nhibernate can not do that, if I am wrong please help me I need to solve this problem, thanks.
a different object with the same identifier value was already associated with the session: 72, of entity: DAL.Ent.Sale
also mention that my database if that income allows the same product at a different price because it has a unique identifier that makes them different.

Going from the information that you have provided, I would say that you need to look at the way your Domain objects are modeled.
You need to separate the product and the price of that product for a given store. There needs to be a joining table in the middle to hold the relationship between a store, the product and the price of the product. So that there is only one price for a product for a given store per record.
So you end up with something like this.
public class Product
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual ISet<Price> Prices { get; set; }
}
public class Price
{
public virtual Guid Id { get; set; }
public virtual Product Product { get; set; }
public virtual Store Store { get; set; }
public virtual decimal Price { get; set; }
}
public class Store
{
public virtual Guid Id { get; set; }
public virtual string Name { get; set; }
public virtual ISet<Price> ProductPrices { get; set; }
}

Related

Merge multiple objects

I'am having some problems with an issue that I've encountered. I'm creating a webshop, where it is possible for a logged-in and a non-logged-in user to add products to their basket. When the user checkeouts the user will have to either log in or sign up. In case the user logs in on an existing account and that account already have a basket with products, it is a must to merge the two baskets into one. Below is my two tables (BasketTable) and (BasketProductTable).
public partial class BasketTable
{
public BasketTable()
{
this.BasketProductTables = new HashSet<BasketProductTable>();
this.OrderTables = new HashSet<OrderTable>();
}
public int BasketId { get; set; }
public Nullable<int> UserId { get; set; }
public string SessionId { get; set; }
public Nullable<System.DateTime> Registered { get; set; }
public virtual ICollection<BasketProductTable> BasketProductTables { get; set; }
public virtual UserTable UserTable { get; set; }
public virtual ICollection<OrderTable> OrderTables { get; set; }
}
public partial class BasketProductTable
{
public int BasketProductId { get; set; }
public int BasketId { get; set; }
public int ProductId { get; set; }
public Nullable<int> Quantity { get; set; }
public Nullable<double> TotalSum { get; set; }
public virtual BasketTable BasketTable { get; set; }
public virtual ProductTable ProductTable { get; set; }
}
My question is that I'm uncertain how to merge the baskets. If someone could navigate me to a good article on the subject or show some code then I would be happy. I am coding in Asp.Net (MVC) and using Linq to entity.
- Jakob
----- UPDATE ------
I decided to use two foreach containing the old and new baskets. I checked on if the item from the new basket existed in the old basket then I would update it with quantity and totalSum. If it didn't exist then I would create a new object with its information and then delete all the items in the old. I found out that the items wouldn't be created/updated in runtime so I had problems checking if a product had been created in the foreach, so I created a list where I would add the created/updated products on their productId and check in the code if the product was added to the list before either creating or updating. I hope this helps someone.
I would argue that a better experience is to merge the baskets in such a way that "duplicated" orders are ignored. Here's some rough pseudo-code - something like:
foreach (BasketProductTable newBasketProduct in newBasket.BasketProductTables) {
if(oldBasket.Contains(newBasketProduct)) {
continue; // this ignores duplicate order items
}
// Otherwise add it to the old basket
oldBasket.Add(newBasketProduct);
}
Where newBasketTable is your new Basket of goods, and oldBasket is the existing saved basket.
After this you can discard the "new basket" as your "old basket" has the new items. A word of caution: don't forget to re-calculate the price on each individual item, as the price may have changed since the user last placed the item in their basket.

Asp.net code first many to one

Well it's a noob question but i can't figure out the solution.
I have two entities, user and team. User can create a team and invite other users. User can belong only one team but team has multiple users.
What would be the most correct relationship between users and team? I also need DateJoin in team and other properties. Should i create third table(TeamMembers)?
Here is code what i tried :
public class TeamMember
{
public int Id { get; set; }
[ForeignKey("Team")]
public int TeamId { get; set; }
public Team Team { get; set; }
[ForeignKey("User")]
public string UserId { get; set; }
public User User { get; set; }
public DateTime DateJoin { get; set; }
public RoleEnum MemberRole { get; set; }
}
public enum RoleEnum
{
Capitan = 1,
Main,
Sub
}
And team has list of members:
public class Team
{
public int Id { get; set; }
public string Name { get; set; }
public int Score { get; set; }
public ICollection <TeamMember> Members { get; set; }
}
But third table means many to many relationship...
If the user can only belong to one team then this is the correct format.
However, if you think you might change this policy in the future then I do suggest you use a many to many relationship. This would also allow you to keep track of the previous teams your users belonged to, by simply using a "DateLeave" property for example.

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.

Should objects further down a hierarchy reference the root?

My stack is ASP.NET MVC 5, Entity Framework 6.1, code-first, SQL Server.
I'm working on an application which involves multiple schools, each of which have courses (each which have sections) and students. These form hierarchies of related objects, which are each rooted by a single school instance.
Basic layout so far:
One school has many courses and students
One course has many sections
Simplified versions of the models follow.
public class School
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Course> Courses { get; set; }
public virtual ICollection<Student> Students { get; set; }
}
public class Student
{
public int Id { get; set; }
public int SchoolId { get; set; }
public virtual School School { get; set; }
public virtual ICollection<Enrolment> Enrolments { get; set; }
}
public class Course
{
public int Id { get; set; }
public string Title { get; set; }
public int SchoolId { get; set; }
public virtual School School { get; set; }
public virtual ICollection<CourseSection> CourseSections { get; set; }
}
public class CourseSection
{
public int Id { get; set; }
public int CourseId { get; set; }
public virtual Course Course { get; set; }
public virtual ICollection<Enrolment> Enrolments { get; set; }
}
There are other models and relationships involved, but this should be enough to form the basis for my question.
A course section is related to a course, which in turn relates to a school. Given a course section, I can determine the school it belongs to, e.g. var school = givenSection.Course.School. Conversely, given a school, I can get the course sections belonging to the school. In code it's just a couple of references away, while in the database it's just a couple of table joins. But it gets more interesting still. Consider the next model:
public class Enrolment
{
public int Id { get; set; }
public int StudentId { get; set; }
public int CourseSectionId { get; set; }
public virtual Student Student { get; set; }
public virtual CourseSection CourseSection { get; set; }
}
An Enrolment instance is the many-to-many bridge between students and course sections. Getting a list of enrolments for a school is multiple steps requiring multiple table joins. In a system which might become quite large in number of records, I worry about the efficiency of this setup. Then again, the application is configured for lazy loading, so maybe that's OK, I don't yet know enough about EF to be certain.
In the interest of simplicity for data retrieval, might it be ideal to reference the school from either of, or both, the CourseSection and Enrolment models? Extending it further, should all models in the hierarchy be able to directly reference the School they belong to?
No, that would break normalization. Your performance concern is valid but the solution cannot be known and should not be implemented prematurely and without measuring actual timings. In my opinion the data is the most important thing because chances are it will outlive the code. Therefore all else equal the good shape of the data should be e priority.

Entity Framework Annotation with two tables pointing at each other

I am trying to use CodeFirst to generate my database.
I have two tables Staff and Team, There is one Team Leader in each team that is a foreign key to a staffID, and each staff is associated to one Team.
public class Staff
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string Username { get; set; }
public string PasswordHash { get; set; }
public string Salt { get; set; }
public string Token { get; set; }
public string Mobile { get; set; }
public string Email { get; set; }
public bool Admin { get; set; }
public bool Active { get; set; }
public int TeamID { get; set; }
[ForeignKey("TeamID")]
public Team Team { get; set; }
}
public class Team
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public int TeamLeaderID { get; set; }
[ForeignKey("TeamLeaderID")]
public Staff TeamLeader { get; set; }
}
Because each one is pointing to the other I get an error Unable to determine the principal end of an association between the types 'Team' and 'Staff'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations. How do I annotate it in such a way that it understands why I am doing this.
Think about it this way... what comes first the team or the team leader? If you try to create a team leader you can't because you have to first specify a team! But if you want to create a team you can't because you must specify who the team leader is according to your foreign key constraints.
You will have to ease up in some way and either make it so that a team can have an optional team leader, or a staff member can optionally belong to a team.
You do this by changing one of the foreign key IDs to a nullable type:
public int? TeamLeaderID { get; set; }
Your code seems like you are trying to include business rule enforcement/responsibility via referential integrity. You have a one to many relationship your Team -> Staff. You just add a boolean for the TeamLeader. Your logic before doing a database write should check to see if you have an existing TeamLeader or not already.
public class Staff
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string Username { get; set; }
public string PasswordHash { get; set; }
public string Salt { get; set; }
public string Token { get; set; }
public string Mobile { get; set; }
public string Email { get; set; }
public bool Admin { get; set; }
public bool Active { get; set; }
public IsTeamLeader { get; set; }
}
public class Team
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
//virtual keyword tells Code First to create the proper Foreign Key relationship
public virtual List<Staff> Members{ get; set; }
}
If you had a large system, with many developers, you could use the fluent API to accomplish your goal and enforce your team leader rule at the database level, thus preventing an out of touch developer from inadvertently adding a second team leader to any give team but if this is a small to normal size project, with small teams that are aware of the basics of the company/project than a simple one to many relationship will accomplish the mission and you can rely on your business rules/logic to enforce/protect the database data so that there is one team leader for any given team at any give time. Consider an AddUpdateTeamMember type method that is called by everyone that enforces the team leader requirement. A stored procedure is another great way to easily solve this problem if you are still considering a model first approach and still experimenting with code first.
Consider too, what if there was a need for two team leaders on one team at some future point of time in the project, database might get too inconveniently "locked down" to scale to this change.

Categories

Resources