I am using entity-framework in mvc. I am receiving this error while generating view.I am using MVC controller with read/write actions and views, using EF. I am Trying to generate a list using scaffold template.
This Entity Framework auto generated class
namespace WebApplication3.Models
{
using System;
using System.Collections.Generic;
public partial class Employee
{
public int EmployeeId { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
public string City { get; set; }
public Nullable<System.DateTime> DOB { get; set; }
public Nullable<int> DepartmentId { get; set; }
public virtual TblDepartment TblDepartment { get; set; }
}
}
Here is my Controller Code :
public ActionResult EmployeesByDep()
{
var employees = db.Employees.Include("TblDepartment").GroupBy(x => x.TblDepartment.DepName)
.Select(y => new TotalDepartments
{
DepName = y.Key,
Total = y.Count()
}
).ToList().OrderByDescending(y=>y.Total);
return View(employees);
}
Model Code:
public string DepName { get; set; }
public int Total { get; set; }
The problem is because you had not declared a key.
You should create a new class EmployeeMetaData.cs
With:
[MetadataType(typeof(EmployeeMetaData))]
public partial class Employee
{
}
public class Employee
{
[Key]
public int EmployeeId { get; set; }
}
add: using System.ComponentModel.DataAnnotations;
Related
I am new to ASP.NET, how can I make my item table save the categoryID which I get from the category table? As an example I want the item "Apple mobile phone" to have the category ID which refers to category name which is electronics, I hope you got the picture.
Here is model:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace WebApplication1.Models
{
public class itemTable
{
[Key]
public int Id { get; set; }
public string company { get; set; }
public string availability { get; set; }
public decimal price { get; set; }
public decimal discount { get; set; }
public decimal tax { get; set; }
public string description { get; set; }
public int categoryid { get; set; }
}
public class categories
{
[Key]
public int categoryID { get; set; }
public string categoryName { get; set; }
}
}
And here is my DbContext:
using Microsoft.EntityFrameworkCore;
using System.Diagnostics;
using WebApplication1.Models;
namespace WebApplication1.Context
{
public class itemTableDbContext : DbContext
{
public itemTableDbContext(DbContextOptions options) : base(options)
{
}
public DbSet<itemTable> ItemTables { get; set; }
public DbSet<categories> categories { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<itemTable>().ToTable("itemtable");
modelBuilder.Entity<categories>().ToTable("categories");
}
}
}
I tried all the possible ways but there is always something wrong, multiple items might be in the same category like phone brand items are all under the "electronics" category
You can configure One-to-One relationship between two entities in such way:
public class ItemTable
{
[Key]
public int Id { get; set; }
public string Company { get; set; }
public string Availability { get; set; }
public decimal Price { get; set; }
public decimal Discount { get; set; }
public decimal Tax { get; set; }
public string Description { get; set; }
public virtual Category Category { get; set; }
}
public class Category
{
[Key]
[ForeignKey("ItemTable")]
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public virtual ItemTable ItemTable { get; set; }
}
Note: Better to use PascalCase in C#
I want to add a many-to-many-relationship to my database using EF 6.
I want to add a many to many between the AppUser and Courses. Here are my models:
AppUser
using Microsoft.AspNetCore.Identity;
using System;
using System.Collections.Generic;
namespace WebApplication2.Models
{
public class AppUser : IdentityUser<Guid>
{
public string LastName { get; set; }
public string FirstMidName { get; set; }
public DateTime EnrollmentDate { get; set; }
public IList<AppUserCourse> AppUserCourses { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
}
}
Course
namespace WebApplication2.Models
{
public class Course
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
public virtual ICollection<Enrollment> Enrollments { get; set; }
public IList<AppUserCourse> AppUserCourses { get; set; }
}
}
AppUserCourse (Joined Table)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace WebApplication2.Models
{
public class AppUserCourse
{
public Guid AppUserId { get; set; }
public AppUser AppUser { get; set; }
public int CourseId { get; set; }
public Course Course { get; set; }
}
}
DataContext.cs
using WebApplication2.Models;
using Microsoft.EntityFrameworkCore;
using System;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
namespace WebApplication2
{
public class DataContext : IdentityDbContext<AppUser, AppRole, Guid>
{
public DataContext(DbContextOptions<DataContext> options) : base(options)
{
}
public DbSet<Course> Courses { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<AppUser> AppUsers { get; set; }
public DbSet<AppUserCourse> AppUserCourses { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<AppUserCourse>().HasKey(i => new { i.AppUserId, i.CourseId });
}
}
}
When I know do a migration and update my database, EF is creating my something strange in the AppUserCourses-Table:
It creates my the AppUserId twice (AppUserId and AppuserId1): Former as int and latter as uniqueidentifier.
I would need it just once as unique identifier. When I now try to add a new AppUserCourse, I get the error message:
Operand type clash: uniqueidentifier is incompatible with int.
On your AppUserCourse remove the entities, so it looks like the following, re-create your migrations too
public class AppUserCourse
{
public Guid AppUserId { get; set; }
public int CourseId { get; set; }
}
That will create your many to many link
The following is an example I've set up
public class Player
{
public int Id { get; set; }
public string Firstname { get; set; }
public string Surname { get; set; }
public List<PlayerGroup> PlayerGroups { get; set; }
}
public class PlayerGroup
{
public int PlayerId { get; set; }
public int GroupId { get; set; }
}
public class Group
{
public int Id { get; set; }
public string Name { get; set; }
public List<PlayerGroup> PlayerGroups { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<PlayerGroup>().HasKey(x => new {x.GroupId, x.PlayerId});
}
Creates the following
I have 2 entities like below;
public class Order
{
public int Id { get; set; }
public Description { get; set; }
public virtual Purchase Purchase{ get; set;}
}
public class Purchase
{
public int Id { get; set; }
public Description { get; set;}
public int? OrderId { get; set;}
public virtual Order Order { get; set;}
}
Here I create order first.
Based on order i can create purchase.
Purchase can be happened without order also. So it is Nullable foreign key.
For one order, it should have only one purchase. So OrderId is unique also.
How can i specify this relationship in Code First
You can specify a unique attribute like this. You just can't make a unique index the target of a foreign key in EF6.
public class Order
{
public int Id { get; set; }
public string Description { get; set; }
public virtual Purchase Purchase { get; set; }
}
public class Purchase
{
public int Id { get; set; }
public string Description { get; set;}
[Index(IsUnique = true)]
public int? OrderId { get; set; }
public virtual Order Order { get; set; }
}
But EF won't allow a 1-1 relationship to a non-key column, but something like this has the desired relational model:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp5
{
public class Order
{
public int Id { get; set; }
public string Description { get; set; }
internal ICollection<Purchase> Purchases { get; } = new HashSet<Purchase>();
public Purchase Purchase { get { return Purchases.FirstOrDefault(); } }
}
public class Purchase
{
public int Id { get; set; }
public string Description { get; set; }
[Index(IsUnique = true)]
public int? OrderId { get; set; }
[ForeignKey("OrderId")]
public virtual Order Order { get; set; }
}
public class Db : DbContext
{
public DbSet<Order> Orders { get; set; }
public DbSet<Purchase> Purchases { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Order>().HasMany(o => o.Purchases).WithOptional(p => p.Order);
}
}
class Program
{
static void Main(string[] args)
{
Database.SetInitializer(new DropCreateDatabaseAlways<Db>());
int OrderId;
using (var db = new Db())
{
var o = db.Orders.Create();
o.Description = "New Order";
var p = db.Purchases.Create();
p.Order = o;
p.Description = "New Purchase";
db.Orders.Add(o);
db.Purchases.Add(p);
db.SaveChanges();
OrderId = o.Id;
}
using (var db = new Db())
{
var p = db.Purchases.Create();
p.OrderId = OrderId;
p.Description = "Another Purchase";
db.Purchases.Add(p);
db.SaveChanges(); //fails
}
}
}
}
David
In the comments to your question, you indicated:
I need to make it (OrderId) unique also
You cannot do that that because EF does not support unique columns except keys.
You may use an index which will allow you to make the index unique but you cannot have a unique key.
I have a products table which has a CategoryId which represents the respective primary key from the Categories table.
ProductViewModel
public ProductVM(ProductDTO productDTO)
{
Id = productDTO.Id;
Name = productDTO.Name;
Description = productDTO.Description;
Price = productDTO.Price;
CategoryId = productDTO.CategoryId;
ImageName = productDTO.ImageName;
}
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
public decimal Price { get; set; }
public int? CategoryId { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
public string ImageName { get; set; }
public IEnumerable<string> GalleryImages { get; set; }
Product DTO
public class ProductDTO
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Slug { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int CategoryId { get; set; }
public string ImageName { get; set; }
[ForeignKey("CategoryId")]
public virtual CategoryDTO Category { get; set; }
}
This is how I get a list of products:
List<ProductVM> productVM;
using (Db db = new Db())
{
productVM = db.Products
.ToArray()
.Select(x => new ProductVM(x))
.ToList();
}
As you can see I am passing the CategoryId around and I can display it in my views with the ProductVM ViewModel, but I also want to get the Name of the category in there as well.
I can think of some hacks, e.g. accessing the DB from the constructor in the ViewModel based on the CategoryId and assigning it that way, but I wanna see if there is a more elegant solution?
Bottom line - I have a Name column in my Categories table and I want to pass that name to the ProductVM in a most effective way.
Add a property to you model for the category name, say
public string CategoryName { get; set; }
and modify the constructor to populate it
public ProductVM(ProductDTO productDTO)
{
CategoryName = productDTO.Category.Name;
....
and modify the query to
List<ProductVM> productVM = db.Products.AsEnumerable().Include(x => x.Category)
.Select(x => new ProductVM(x)).ToList();
Note that you view model also required a parameterless constructor if your using this for editing otherwise an exception will be thrown in the POST method.
Note also that you do not need the using (Db db = new Db())
The best solution is the following (I removed all other answers)
namespace Test
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
internal class Program
{
private static void Main(string[] args)
{
List<ProductVM> productVM;
//It doesn't matter if you use a using block or not
using (Db db = new Db())
{
db.Database.Log = Console.WriteLine;//To see the generated SQL
productVM = db.Products
.Include(p => p.Category)
.Select(p => new ProductVM
{
Id = p.Id,
Name = p.Name,
Description = p.Description,
Price = p.Price,
CategoryId = p.CategoryId,
CategoryName = p.Category.Name,
ImageName = p.ImageName,
}).ToList();
}
Console.ReadKey();
}
}
public class Db : DbContext
{
public DbSet<ProductDTO> Products { get; set; }
public DbSet<CategoryDTO> Categories { get; set; }
}
public class ProductDTO
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public string Slug { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int CategoryId { get; set; }
public string ImageName { get; set; }
[ForeignKey("CategoryId")]
public virtual CategoryDTO Category { get; set; }
}
public class CategoryDTO
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
}
public class ProductVM
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Description { get; set; }
[Required]
public decimal Price { get; set; }
public int? CategoryId { get; set; }
public string CategoryName { get; set; }
public string ImageName { get; set; }
}
}
I am trying to update a CART. When I am doing the search for it, it fails. It used a GUID since the user is not logon. I don't know if I have to re-update the DBEntities maybe ? not sure.
I got this error : The specified type member 'CartId' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.
Thanks
ShoppingCart.cs
namespace Tp1WebStore3.Models
{
public partial class ShoppingCart
{
Tp1WebStoreDBEntities db = new Tp1WebStoreDBEntities();
string ShoppingCartId { get; set; }
public const string CartSessionKey = "CartId";
public static ShoppingCart GetCart(HttpContextBase context)
{
var cart = new ShoppingCart();
cart.ShoppingCartId = cart.GetCartId(context);
return cart;
}
// Helper method to simplify shopping cart calls
public static ShoppingCart GetCart(Controller controller)
{
return GetCart(controller.HttpContext);
}
public void AddToCart(Produit produit)
{
// Get the matching cart and album instances
var cartItem = db.Paniers.SingleOrDefault(
c => c.CartId == ShoppingCartId &&
c.ProduitId == produit.ProduitId); <== the error happen here
Panier.cs
namespace Tp1WebStore3.Models
{
using System;
using System.Collections.Generic;
public partial class Panier
{
public int PanierId { get; set; }
public string CartId { get; set; }
public int ProduitId { get; set; }
public int Quantite { get; set; }
public decimal Prix { get; set; }
public System.DateTime DateCree { get; set; }
public virtual Produit Produit { get; set; }
}
}
produit.cs
namespace Tp1WebStore3.Models
{
using System;
using System.Collections.Generic;
public partial class Produit
{
public Produit()
{
this.Paniers = new HashSet<Panier>();
}
public int ProduitId { get; set; }
public int CategorieId { get; set; }
public string Description { get; set; }
public int Quantite { get; set; }
public decimal Prix { get; set; }
public virtual Categorie Categorie { get; set; }
public virtual ICollection<Panier> Paniers { get; set; }
}
}
If you changed things in the database you have to update the Data model. Right click inside your .edmx file where your entity diagram is and click Update model from db