Merge multiple objects - c#

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.

Related

Entity Framework right join to fill user settings

Not sure how to describe this question.
Here is the example:
I have an entity as Tour. Tour table contains static 3 rows(can be more in the future).
public class Tour
{
public int Id { get; set; }
public string Name { get; set; }
public string Location { get; set; }
}
Each user can turn this options keys.
So I have another table called UserTourSetting to store user options.
public class UserTourSetting
{
public int Id { get; set; }
public int UserId { get; set; }
public int TourId { get; set; }
public bool Enabled { get; set; }
public ApplicationUser User { get; set; }
public Tour Tour { get; set; }
}
When the user loads the page it should always see 3 rows with the status on or off.
When I load UserTourSetting table I get no results as there is no record yet on the table for the user first time. I guess I need to do join with Tour table and also include Tour results as I will need the titles.
When the switches are turned on off then individually it will add a new record if not exists or change Enabled key if exists.
What would be the best way to implement this with EF? I struggle the generate linq statement to load the join table.
here is the method I tried:
public IEnumerable<UserTourSetting> GetUserTourSettings(int userId)
{
var q = from tour in DbContext.Tours
join uts in DbContext.UserTourSettings
on tour.Id equals uts.TourId
where uts.UserId == userId
select uts;
return q;
}
But it does not work. And I cannot access Tour names. Where the include can go in this query?
Thanks,
Please try to set virtual on those properties.
public virtual ApplicationUser User { get; set; }
public virtual Tour Tour { get; set; }
p/s: for more information, you can see this https://stackoverflow.com/a/8542879/5771430

Can a class behave differently based on the context it's used within?

My problem is that I want to use one class in two classes but there will be properties that shouldn't exist in one of them. For example a warehouse ships items to the branches, the item in the branch should have DiscountPercentage property but it doesn't exist in the warehouse. Also there is a connection between the two instances of items in both classes (Warehouse and Branch): when items are added to a branch the quantity should be subtracted from the quantity (property) in the warehouse.
I'm thinking of the OOP concepts, how it can help, but I'm totally confused.
I created a class for the Item:
public class Item
{
public Item()
{
this.Categories = new HashSet<Category>();
}
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public int Quantity { get; set; }
[Required]
public decimal Price { get; set; }
[Range(0, 100), Display(Name = "Discount Percentage"), RegularExpression("([1-9][0-9]*)", ErrorMessage = "Enter only numeric number")]
public double? DiscountPercentage { get; set; } = 0;
public ICollection<Category> Categories { get; set; }
public ICollection<Order> Orders { get; set; }
public ICollection<Branch> Branches { get; set; }
}
public class Branch
{
public int Id { get; set; }
public string Location { get; set; }
public ICollection<Item> Items { get; set; }
}
public class Warehouse
{
public int Id { get; set; }
public ICollection<Item> Items { get; set; }
public ICollection<Branch> Branches { get; set; }
}
The problem in my code is that the item in the warehouse is the same as in the branch's, which is not true and also not wrong, how OOP can handle this situation?
In proper class design, the DiscountPercentage is not a property of the item. It’s also not a property of the branch. Instead, it’s a property of the relation between the branch and an item:
So what you would do is create some BranchItem type which essentially just sits between them and defines the relationship including additional properties:
public class BranchItem
{
public Branch Branch { get; set; }
public Item Item { get; set; }
public double DiscountPercentage { get; set; }
}
One wonders if you actually need Branch and Warehouse objects at all, or whether each item could simply have a property location.
In any case, the OO way to solve the problem as stated is to create a new class, say, WarehouseItem which contains everything that a Warehouse should be able to access in an Item. Then, extend WarehouseItem with Item and add whatever properties you need in Branch. Inside Warehouse, you should only interact with WarehouseItems, even if the objects are actually of type Item. This is pretty textbook polymorphism.
(One caveat: Generally you would want the simpler class with less properties to have the more generic name i.e. Item and the extension with more properties to have a more specific name. So, my example is not perfect.)

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.

Non unique object nhibernate 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; }
}

Code first one-to-many with two of same entity

Excuse my confusing title, but its not easy to say it in short.
I'm having problems defining a many-to-many relationship in my code first model.
This is my first project using the code first framework, and I need some help.
I got two models, Item and Trade. And the story behind it all is that im building a item trading website.
A trade involve one or many items beeing sent from person A to person B, and one or many items are sent back from person B to person A, completing the trade.
One item belongs to one trade only, but one trade can have many items.
This is how my models look so far.
Item
public class Item
{
public int ItemId { get; set; }
public string Name { get; set; }
public int TradeId { get; set; }
[ForeignKey("TradeId")]
public virtual Trade Trade { get; set; }
}
Trade
public class Trade
{
public int TradeId { get; set; }
public virtual ICollection<Item> ItemsToSend { get; set; }
public virtual ICollection<Item> ItemsToReturn { get; set; }
}
But when trying to run update-database I get the following error.
System.Data.SqlClient.SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.Items_dbo.Trades_TradeId". The conflict occurred in database "MyDB", table "dbo.Trades", column 'TradeId'.
Any help is much appreciated, thanks!
I solved it for now by just adding a flat structure of items and trades. Like a many to many on items and trades.
Since I know the owner of each item, I can also sort out sender and returner by adding senderId and returnerId on the trade.
This is how my model looks like now.
Item
public class Item
{
public int ItemId { get; set; }
public string Name { get; set; }
public virtual ICollection<Trade> Trades { get; set; }
}
Trade
public class Trade
{
public int TradeId { get; set; }
public virtual UserProfile SendUser { get; set; }
public virtual UserProfile ReturnUser { get; set; }
public virtual ICollection<Item> Items { get; set; }
}
This works for now..
This: "One item belongs to one trade only, but one trade can have many items." sounds like one-to-many?
If you can do without the back-reference from Item to Trade then the mapping will be a lot simpler.
This model will map without any configuration:
public class Trade
{
public int Id { get; set; }
public virtual ICollection<Item> ItemsToSend { get; set; }
public virtual ICollection<Item> ItemsToReturn { get; set; }
}
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
}
Inserting data using this code:
var trade = new Trade
{
ItemsToReturn = new [] { new Item{ Name = "Item to return 1"}, new Item{ Name = "Item to return 2"}},
ItemsToSend = new [] { new Item{ Name = "Item to send 1"}, new Item{ Name = "Item to send 2"} }
};
context.Trades.Add(trade);
context.SaveChanges();
Will produce an Item table looking like this:
And a Trades table containing a single row with a single Id column.
If you need to navigate from an Item to the Trade it belongs to you could do that doing a query.
E.g to get the Trade that Item with id = 3 belongs to you can do this:
using (var db = new TradingContext())
{
var tradeOfItem3 = db.Trades.
FirstOrDefault(t => t.ItemsToReturn.Any(i => i.Id == 3) || t.ItemsToSend.Any(i => i.Id == 3));
}

Categories

Resources