trying to make an ecommerce website in asp.net mvc5 - entity-framework

I am trying to make an ecommerce website using entity framework code first but am having a problem with the basket I don't need add bank accounts or any kind the payment method is pay on delivery I got the Icon ready as a button
<dd>
#Html.ActionLink("Add","Basket",new { id = this.Model.Id },new { #class = "btn btn-primary"})
</dd>
once clicked it will activate the action method
public ActionResult Basket(int Id)
{
PB.basket(Id);
return View();
}
witch will activate a method called basket
public void basket(int Id)
{
List<Basket> bst = new List<Basket>();
var user = HttpContext.Current.Session.SessionID;
var prd = db.Products.Where(p => p.Id == Id).FirstOrDefault();
bst.Add(new Basket()
{
Price = prd.Price,
ProductId = prd.Id,
Count = 1,
}) ;
}
here are the classes witch the database for it is created
using identity
public class users
{
public string Id { get; set; }
public string UserName { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string PhoneNumber { get; set; }
}
public class Product
{
public int Id { get; set; }
[Display(Name = "Product Name")]
public string ProductName { get; set; }
[DataType(DataType.ImageUrl)]
public string Image { get; set; }
public string Category { get; set; }
public double Price { get; set; }
[DataType(DataType.Text)]
public string Description { get; set; }
[NotMapped]
public HttpPostedFileBase ImageFile { get; set; }
}
public class Basket
{
public int Id { get; set; }
public int ProductId { get; set; }
public int Count { get; set; }
public double Price { get; set; }
public ApplicationUser user { get; set; }
public Product Product { get; set; }
public ICollection<Product> products { get; set; }
public ICollection<ApplicationUser> users { get; set; }
}
please help

Related

Error adding an object to a field list Entity Framework

Sorry if I don't respect the conventions, I'm new here.
I have a problem in my learning of ASP.NET Core and Entity Framework.
I have bets and users that can have multiple bets. The bets can have no users (they are just displayed on the site and users add them to their account).
Here are my two models :
Bets :
public class Bets
{
public int Id { get; set; }
public string name { get; set; }
public string description { get; set; }
public double team1 { get; set; }
public double team2 { get; set; }
public string sport { get; set; }
public bool enabled { get; set; } // 1 = yes 2 = no
public virtual User user {get;set;}
public int? UserId {get;set;}
}
User :
public class User
{
public int UserId { get; set; }
public string Username { get; set; }
public byte[] PasswordHash { get; set; }
public byte[] PasswordSalt { get; set; }
public double moneyBalance { get; set; }
public int admin { get; set; }
public virtual ICollection<Bets> bets {get; set;}
}
Then I tried to add a bet that already existed to a user:
public async Task<bool> addUserBet(int id, Bets bet)
{
var user = await _context.Users.FirstOrDefaultAsync(u => u.UserId == id);
if (!(user.bets == bet))
{
user.bets.Add(bet);
await _context.SaveChangesAsync();
return true;
}
return false;
}
The controller :
[AllowAnonymous]
[HttpPut("addBetUser/{id}")]
public async Task<IActionResult> AddBetUser(int id, BetForAddToUserDto betForAddTo)
{
Bets bets = new Bets();
_mapper.Map(betForAddTo, bets);
await _repo.addUserBet(id, bets);
await _repo.SaveAll();
return StatusCode(200);
}
But I get this error in Postman when I try the endpoint above:
What am I doing wrong that I don't understand? Please help me, thank you :)
I tried to add a bet that already existed to a user
If you have existed a bet and a user.And you want to add this bet to the user.
Here is a working demo like below:
1.Model:
public class Bets
{
public int Id { get; set; }
public string name { get; set; }
public string description { get; set; }
public double team1 { get; set; }
public double team2 { get; set; }
public string sport { get; set; }
public bool enabled { get; set; } // 1 = yes 2 = no
public virtual User user { get; set; }
public int? UserId { get; set; }
}
public class User
{
public int UserId { get; set; }
public string Username { get; set; }
public byte[] PasswordHash { get; set; }
public byte[] PasswordSalt { get; set; }
public double moneyBalance { get; set; }
public int admin { get; set; }
public virtual IList<Bets> bets { get; set; }
}
public class BetForAddToUserDto
{
public int Id { get; set; }
public string name { get; set; }
public string description { get; set; }
public double team1 { get; set; }
public double team2 { get; set; }
public string sport { get; set; }
public bool enabled { get; set; } // 1 = yes 2 = no
public virtual User user { get; set; }
public int? UserId { get; set; }
}
2.Controller:
public async Task<bool> addUserBet(int id, Bets bet)
{
var user = await _context.User.FirstOrDefaultAsync(u => u.UserId == id);
if (!(user.bets == bet))
{
bet.UserId = id;
_context.Bets.Update(bet);
await _context.SaveChangesAsync();
return true;
}
return false;
}
[AllowAnonymous]
[HttpPut("addBetUser/{id}")]
public async Task<IActionResult> PutUser(int id, BetForAddToUserDto betForAddTo)
{
Bets bets = new Bets();
_mapper.Map(betForAddTo, bets);
var bet = _context.Bets.Find(bets.Id);
await addUserBet(id, bet);
return StatusCode(200);
}
3.Profile:
public class AutoMapping: Profile
{
public AutoMapping()
{
CreateMap<Bets, BetForAddToUserDto>().ReverseMap();
}
}
4.Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddAutoMapper(typeof(AutoMapping));
}
This:
if (!(user.bets == bet))
User.bets is a collection, you cannot compare it to a single bet
The right way to check it would be:
if (!(user.bets.Any(b => b.ID == bet.ID)))
Also you are not passing in anything for this parameter:
BetForAddToUserDto betForAddTo

IAsyncEnumerable cannot be used for parameter of type IEnumerable

I have entities, service and view models. I use the service models in the services and in the service I map from entity to the service model and I return IQueryable<UserServiceModel> and I use the service in the controller but when I try to materialize the result and map it to the view model with Select it throw exception:
ArgumentException: Expression of type 'System.Collections.Generic.IAsyncEnumerable1[TestDriveServiceModel]' cannot be used for parameter of type 'System.Collections.Generic.IEnumerable1[TestDriveServiceModel]' of method 'System.Collections.Generic.List1[TestDriveServiceModel] ToList[TestDriveServiceModel](System.Collections.Generic.IEnumerable1[TestDriveServiceModel])'
Parameter name: arg0
// the service map from entities to service models and returns them
// userServiceModels is the result of the service
// Here the error is thrown
var viewModel = await userServiceModels.Select(usm => new UserViewModel()
{
TestDrivesCount = usm.TestDrives.Count()
}).ToListAsync();
public class UserServiceModel : IdentityUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<TestDriveServiceModel> TestDrives { get; set; } = new List<TestDriveServiceModel>();
}
public class TestDriveServiceModel
{
public string Id { get; set; }
public string CarId { get; set; }
public CarServiceModel Car { get; set; }
public string UserId { get; set; }
public UserServiceModel User { get; set; }
public string StatusId { get; set; }
public StatusServiceModel Status { get; set; }
public DateTime ScheduleDate { get; set; }
public string Comment { get; set; }
}
public class User : IdentityUserEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public ICollection<TestDriveEntity> TestDrives { get; set; } = new List<TestDriveEntity>();
}
public class TestDriveEntity
{
public string Id { get; set; }
[Required]
public string CarId { get; set; }
public BaseCarEntity Car { get; set; }
[Required]
public string UserId { get; set; }
public User UserEntity { get; set; }
[Required]
public string StatusId { get; set; }
public Status StatusEntity { get; set; }
[Required]
public DateTime ScheduleDate { get; set; }
public string Comment { get; set; }
}

Method based linq queries

I have five tables in database whose Entity classes are as follows -
Product
public int ProductId { get; set; }
public string Name { get; set; }
public int Category { get; set; }
public string Description { get; set; }
public string Brand { get; set; }
public virtual ProductCategory ProductCategory { get; set; }
public virtual ICollection<ProductImage> ProductImages { get; set; }
public virtual ICollection<ProductVariantMapping> ProductVariantMappings
ProductCategory
public int CategoryId { get; set; }
public string Name { get; set; }
public virtual ICollection<Product> Products { get; set; }
ProductImage
public int ProductImageId { get; set; }
public int ProductId { get; set; }
public byte[] Image { get; set; }
public virtual Product Product { get; set; }
ProductVariantMapping
public int MappingId { get; set; }
public int ProductId { get; set; }
public int ProductVariantId { get; set; }
public string Value { get; set; }
public System.Guid GUID { get; set; }
public virtual Product Product { get; set; }
public virtual ProductVariant ProductVariant { get; set; }
ProductVariant
public int ProductVariantId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<ProductVariantMapping> ProductVariantMappings
I want to get Product Details which should include ProductId, ProductName, Category, Description, Brand, Image(Only 1 for now), and Variants*
*Variants would be a list of all the variants of a product. A single variant can be a combination of all the VariantIds with same GUIDs. (VariantName is in ProductVariant table and VariantValue is in ProductVariantMapping table and Price is in inventory table).
So, I used method-based linq for this purpose.
EkartEntities ekartEntities = new EkartEntities();
var productDetails = ekartEntities.Products.Include(p =>
p.ProductVariantMappings).Include(p => p.ProductImages).Include(p =>
p.ProductCategory).Where(p => p.ProductId ==
productDetailDTO.ProductId).ToList();
Now I have to convert my product into a ProductDetailDTO.
ProductDetailDTO
public class ProductDetailDTO
{
public int ProductId { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public byte[] Image { get; set; }
public string Description { get; set; }
public string Brand { get; set; }
public List<Variant> Variants { get; set; }
}
public class Variant
{
public string Name { get; set; }
public string Value { get; set; }
public System.Guid Guid { get; set; }
public decimal Price { get; set; }
}
I started doing this like this -
void ToDTO(List<Product> products)
{
EkartEntities ekartEntities = new EkartEntities();
ProductDetailDTO productDetailDTO = new ProductDetailDTO();
foreach (var item in products)
{
productDetailDTO.ProductId = item.ProductId;
productDetailDTO.Name = item.Name;
productDetailDTO.Category = item.ProductCategory.Name;
productDetailDTO.Description = item.Description;
productDetailDTO.Brand = item.Brand;
productDetailDTO.Image = item.ProductImages.ElementAt(0).Image;
foreach (var variant in item.ProductVariantMappings)
{
productDetailDTO.Variants = variant.ProductVariant // ?
}
}
}
I don't know how do I proceed further. How can I extract the variant based on the GUIDs?
The logic of combining of ProductVariant entries with same GUID in mapping table doesn't seem clear from the question, however you can group entries in ProductVariantMappings by GUID and then add any logc you like on group. Here is an example where I take first name and value in a groub of variant with the same GUID:
void ToDTO(List<Product> products)
{
EkartEntities ekartEntities = new EkartEntities();
ProductDetailDTO productDetailDTO = new ProductDetailDTO();
foreach (var item in products)
{
productDetailDTO.ProductId = item.ProductId;
productDetailDTO.Name = item.Name;
productDetailDTO.Category = item.ProductCategory.Name;
productDetailDTO.Description = item.Description;
productDetailDTO.Brand = item.Brand;
productDetailDTO.Image = item.ProductImages.ElementAt(0).Image;
productDetailDTO.Variants = item.ProductVariantMappings
.GroupBy(pm => pm.GUID)
.Select(g => new Variant
{
Guid = g.Key,
// Here should be some logic for getting a name of the combination of Variants
// I just take first
Name = g.FirstOrDefault()?.ProductVariant?.Name,
// Here should be some logic for getting a value of the combination of Variants
// Take first again
Value = g.FirstOrDefault()?.Value,
Price = // need inventory table to compute price
})
.ToList();
}
}
Also note that you need somehow add relation to inventory table, which is not presented in question. Hope it helps.

Entity framework navigation property is null

I have two models using Entity Framework.
public class Player
{
public int PlayerId { get; set; }
public string Name { get; set; }
public string Sex { get; set; }
public string Plays { get; set; }
public string FavouriteSurface { get; set; }
}
public class SinglesMatch
{
public int SinglesMatchId { get; set; }
public int Player1Id { get; set; }
public int Player2Id { get; set; }
public int PlayerIdWinner { get; set; }
public DateTime Date { get; set; }
public string Venue { get; set; }
public string Score { get; set; }
public List<Player> Players { get; set; }
}
I am using the below code to attempt to display the Name of the player, based on the PlayerId in the SinglesMatch model matching the PlayerID from the Player model.
#foreach (var item in #Model)
{
<ul id="Players" class="bg-success"></ul>
<br/>
<h3>Date - #Html.DisplayFor(#modelItem => item.Date)</h3>
<li>Venue - #Html.DisplayFor(#modelItem => item.Venue)</li>
<li>Player 1 - #Html.DisplayFor(#modelItem => item.Players.First(p => p.PlayerId == item.Player1Id).Name)</li>
<li>Player 2 - #Html.DisplayFor(#modelItem => item.Players.First(p => p.PlayerId == item.Player2Id).Name)</li>
<li>Score- #Html.DisplayFor(#modelItem => item.Score)</li>
}
Upon debugging, the navigation property is always showing as null when the model is retrieved from my repository.
Am I using the navigation property in the correct fashion ? is there a problem with my query ?
Edit to include DbContext:
public TennisTrackerContext() : base("name=TennisTrackerContext")
{
}
public DbSet<Player> Players { get; set; }
public DbSet<PlayerRecord> PlayerRecords { get; set; }
public DbSet<SinglesMatch> SinglesMatches { get; set; }
public DbSet<DoublesMatch> DoublesMatches { get; set; }
public DbSet<Venue> Venues { get; set; }
}
}
You need to add a bridge table. Sql will create this automatically but you won't have access to the variables unless you create it in c#.
public class Player
{
public int PlayerId { get; set; }
public string Name { get; set; }
public string Sex { get; set; }
public string Plays { get; set; }
public string FavouriteSurface { get; set; }
List<PlayerInMatch> Matches { get; set; }
public Player()
{
Matches = new List<PlayerInMatch>();
}
}
public class PlayerInMatch
{
public int Id { get; set; }
public int PlayerId { get; set; }
[ForeignKey("PlayerId")]
public Player Player { get; set; }
public int SinglesMatchId { get; set; }
[ForeignKey("SinglesMatchId")]
public SinglesMatch SinglesMatch { get; set; }
}
public class SinglesMatch
{
public int SinglesMatchId { get; set; }
public int PlayerIdWinner { get; set; }
public DateTime Date { get; set; }
public string Venue { get; set; }
public string Score { get; set; }
public List<PlayerInMatch> Players { get; set; }
public SinglesMatch()
{
Players = new List<PlayerInMatch>();
}
}
static void Main(string[] args)
{
var match = new SinglesMatch();
match.Players.Select(c => c.Player.Name);
}
You need to make your navigation property virtual to enable lazy/eager loading:
public class SinglesMatch
{
public int SinglesMatchId { get; set; }
public int Player1Id { get; set; }
public int Player2Id { get; set; }
public int PlayerIdWinner { get; set; }
public DateTime Date { get; set; }
public string Venue { get; set; }
public string Score { get; set; }
public virtual List<Player> Players { get; set; }
}
Also, did you define the relationship between SinglesMatch and Singles in fluent api?
EDIT: I see you don't have any relations mapped through annotations or fluent api whatsoever, I suggest you take a look at this:
https://msdn.microsoft.com/en-us/data/jj591617.aspx

Entity Framework 4.3 CF many - to - many relationship saving object?

When creating many to many relationship using EF 4.3 code first approach, I cannot save data to connecting table, also cannot any examples on how to fill this table using saving object to Icollection... Here is my example:
MODELS
public class Hospital
{
//PK
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string County { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public Guid User_Id { get; set; }
//FK
public virtual ICollection<Operator> Operators { get; set; }
}
public class Operator
{
//PK
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Dob { get; set; }
public string Email { get; set; }
//FK
public virtual ICollection<Hospital> Hospitals { get; set; }
}
public class Project: DbContext
{
public DbSet<Hospital> Hospitals { get; set; }
public DbSet<Operator> Operators { get; set; }
}
CONTROLLER
public void AddOperater()
{
Hospital h = new Hospital();
h = db.Hospitals.Single(a=>a.Id ==1);
var o = new Operator();
o.FirstName = "John";
o.LastName = "Doe";
o.Dob = new DateTime(1988,2,12);
o.Email = "johndoe#gmail.com";
o.Hospitals.Add(h);
db.SaveChanges();
}
With this approach I keep getting error here: o.Hospitals.Add(h); even when my Hospital instance is filled with data. How exactly to save data to both tables, the dbo.Operators and dbo.OperatorHospital which is relationship table?
o.Hospitals.Add(h) will fail because the list is a null list. You cannot call Add() on a null list. Typically most people get around this by instantiating the list in the constructor of the entity... like so... the current line is blowing up due to a CSharp issue.
public class Hospital
{
//PK
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string County { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public Guid User_Id { get; set; }
//FK
public virtual ICollection<Operator> Operators { get; set; }
public Hospital()
{
Operators = new List<Operator>();
}
}
public class Operator
{
//PK
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime Dob { get; set; }
public string Email { get; set; }
//FK
public virtual ICollection<Hospital> Hospitals { get; set; }
public Operator()
{
Hospitals = new List<Hospital>();
}
}