EntityType no keys defined - c#

I'm creating an app where users log in via Facebook oAuth and then set up a list of songs. I am getting the following error message:
BandFinderCsharp.Models.IdentityUserLogin: : EntityType 'IdentityUserLogin' has no key defined. Define the key for this EntityType.
BandFinderCsharp.Models.IdentityUserRole: : EntityType 'IdentityUserRole' has no key defined. Define the key for this EntityType.
IdentityUserLogins: EntityType: EntitySet 'IdentityUserLogins' is based on type 'IdentityUserLogin' that has no keys defined.
IdentityUserRoles: EntityType: EntitySet 'IdentityUserRoles' is based on type 'IdentityUserRole' that has no keys defined.
The error message is occurring within my SongsController:
`namespace BandFinder.Controllers.Bread
{
public class SongsController : Controller
{
private SongDBContext db = new SongDBContext();
// GET: Songs
public ActionResult Index()
{
return View(db.Songs.ToList()); <--- This is where the error occurs
}
// GET: Songs/Details/5
public ActionResult Details(long? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Song song = db.Songs.Find(id);
if (song == null)
{
return HttpNotFound();
}
return View(song);
}
// GET: Songs/Create
public ActionResult Create()
{
return View();
}
// POST: Songs/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,UserId,BandId,Title,Artist,Genre,ListId,CreatedOn")] Song song)
{
if (ModelState.IsValid)
{
song.CreatedOn = DateTime.Now;
db.Songs.Add(song);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(song);
}
// GET: Songs/Edit/5
public ActionResult Edit(long? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Song song = db.Songs.Find(id);
if (song == null)
{
return HttpNotFound();
}
return View(song);
}
// POST: Songs/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,UserId,BandId,Title,Artist,Genre,ListId,CreatedOn")] Song song)
{
if (ModelState.IsValid)
{
db.Entry(song).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(song);
}
// GET: Songs/Delete/5
public ActionResult Delete(long? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Song song = db.Songs.Find(id);
if (song == null)
{
return HttpNotFound();
}
return View(song);
}
// POST: Songs/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(long id)
{
Song song = db.Songs.Find(id);
db.Songs.Remove(song);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}`
The thing I don't understand is, this controller has nothing to do with the IdentityUser code..
This is my ApplicationUser Model:
namespace BandFinderCsharp.Models
{
public class ApplicationUser : IdentityUser
{
public ApplicationUser()
{
CreatedOn = DateTime.Now;
this.ProfileImage = new byte[0];
this.facebookImage = new byte[0];
}
public byte[] facebookImage { get; set; }
[MaxLength(32)]
public string FirstName { get; set; }
[MaxLength(32)]
public string LastName { get; set; }
public byte[] ProfileImage { get; set; }
//public virtual ICollection<Instrument> Instruments { get; set; }
//public virtual ICollection<Song> Songs { get; set; }
//public virtual ICollection<Band> Bands { get; set; }
public string Zipcode { get; set; }
[Index]
public float Longitude { get; set; }
[Index]
public float Latitude { get; set; }
[Required]
[DatabaseGenerated(DatabaseGeneratedOption.None)]
public DateTime CreatedOn { get; set; }
//////////////
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<IdentityUserLogin>().HasKey<string>(l => l.UserId);
modelBuilder.Entity<IdentityRole>().HasKey<string>(r => r.Id);
modelBuilder.Entity<IdentityUserRole>().HasKey(r => new { r.RoleId, r.UserId });
base.OnModelCreating(modelBuilder);
}
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
}
}
Why am I getting an error referring to Identity models from the songs controller? There should be no correlation between the two at this point.
The IdentityUser class is a built in .NET class which I don't believe I'm able to edit:
namespace Microsoft.AspNet.Identity.EntityFramework
{
//
// Summary:
// Default EntityFramework IUser implementation
public class IdentityUser : IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>, IUser, IUser<string>
{
//
// Summary:
// Constructor which creates a new Guid for the Id
public IdentityUser();
//
// Summary:
// Constructor that takes a userName
//
// Parameters:
// userName:
public IdentityUser(string userName);
}
}
IdentityUserLogin
namespace Microsoft.AspNet.Identity.EntityFramework
{
//
// Summary:
// Entity type for a user's login (i.e. facebook, google)
public class IdentityUserLogin : IdentityUserLogin<string>
{
public IdentityUserLogin();
}
}

If the ApplicationUser class is the object you're looking to save in the Data Base, then it must contain a field named Id which is by default the primary key of the object to which Entity Framework is linking to.
Your Object should look like:
public class ApplicationUser
{
public int Id { get; set; }
public string Name { get; set; }
}
Or if you want to set a different property as the primary key for the object, you should add the [Key] attribute above that field - and you'll also need to add the System.ComponentModel.DataAnnotations namespace:
public class ApplicationUser
{
public int Id { get; set; }
[Key]
public string Name { get; set; }
}

Looking at your entities, I am missing the [Key] attribute that defines the fields for the primary key.
Look at this question, first answer:
EntityType 'Category' has no key defined. Define the key for this EntityType

Related

EntityFramework 6, update object references in generic controller

I have a generic Controller deriving from ApiController:
public abstract class GenericIntegerIdController<T> : ApiController where T : IObjectWithKey
{
...
[HttpPut]
public async Task<IHttpActionResult> Put([FromBody] T entity)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
Context.Entry(entity).State = EntityState.Modified;
try
{
UpdateReferences(entity);
}
catch (Exception e)
{
return InternalServerError(e);
}
try
{
await Context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (await Context.Set<T>().FindAsync(entity.GetId()) == null)
{
return NotFound();
}
throw;
}
return Ok();
}
...
protected virtual IHttpActionResult UpdateReferences(T entity)
{
return null;
}
}
here is an example controller deriving from this:
public class CarsController : GenericIntegerIdController<Car>{
...
protected override IHttpActionResult? UpdateReferences(Car entity)
{
if (entity.Owner != null)
{
var reference = Context.Owner.Find(entity.Owner.Id);
if (reference == null)
{
return NotFound();
}
entity.Owner = reference;
}
return base.UpdateReferences(entity);
}
}
where IObjectWithKey is just an interface with a key (Id)
in this controller im trying to update the entity recieved from the request using EntityFramework 6 but im having some problems when im updating object references
Example
I have a class Car and a class Person:
public class Car: IObjectWithKey
{
[Key]
public int Id { get; set; }
...
[Required]
public virtual Person Owner { get; set; }
}
public class Person: IObjectWithKey
{
[Key]
public int Id { get; set; }
...
[Required]
public virtual ICollection<Car> Cars { get; set; }
}
if i try to PUT a car modifying for example the model everything works fine but if i try and change the Person no error is given but the person does not get changed.
I searched a bit for what could be the cause, and i think its because only the parent entity is put on a modified state while the entity.Owner is still unmodified so it doesnt get updated when calling SaveChanges
I tried some solution like for example manually setting the state of the children to modified on each controller derived from the generic controller like this:
protected override IHttpActionResult? UpdateReferences(Car entity)
{
if (entity.Owner != null)
{
var reference = Context.Owner.Find(entity.Owner.Id);
if (reference == null)
{
return NotFound();
}
entity.Owner = reference;
//Manually setting the state of the child to Modified
Context.Entry(entity.Owner).State = EntityState.Modified;
}
return base.UpdateReferences(entity);
}
but nothing changes.

How should I update a table that is joined with another table in Entity Framework?

I have the following entities:
namespace SomeDataAccess
{
public partial class Patch
{
public int PatchID { get; set; }
public double Number { get; set; }
}
public partial class PatchFile
{
public int FileID { get; set; }
public int PatchID{ get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
}
And I have the following api model:
namespace Web_API.Models
{
[Table("SomeFiles")]
public class SomeFilesViewModel
{
[Key]
public int FileId { get; set; }
public int PatchNumber{ get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
}
The GET method is implemented successfully as following:
/ GET: api/SomeFiles/5
[ResponseType(typeof(SomeFileViewModel))]
public async Task<IHttpActionResult> GetSomeFileViewModel(int id)
{
var patchFile = await _context.PatchFile.FindAsync(id);
return someFile == null
? (IHttpActionResult)NotFound()
: Ok(new someFileViewModel
{
FileId = patchFile.FileID,
PatchNumber = patch.Number,
Name = patchFile.Name,
Type = patchFile.Type,
});
}
Thus far, I have implemented the PUT method as following:
// PUT: api/SomeFiles
[ResponseType(typeof(void))]
public async Task<IHttpActionResult> PutSomeFileViewModel(SomeFilesViewModel someFileViewModel)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
var file = new SomeDataAccess.PatchFile
{
FileID = someFileViewModel.FileId,
PatchID = _context.Patch.FirstOrDefault(i => i.Number == someFileViewModel.PatchNumber).PatchID
// How to get the relavent patch id by having the patch Number?
Name = someFileViewModel.Name,
Type = someFileViewModel.Type
};
_context.Entry(file).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!FileExists(file.FileID))
return NotFound();
throw;
}
return StatusCode(HttpStatusCode.NoContent);
}
And a sample payload:
Sample PayLoad:
{
"FileId" = 4
"PatchNumber" = 894
"Name" = "MyFile.exe"
Type = "Application"
}
How can I update or add a record to PatchFile entity if I only have the PatchNumber and not the PatchId to prevent conflicted with the FOREIGN KEY constraint?
_context.Patch.FirstOrDefault(i => i.Number == someFileViewModel.PatchNumber).PatchID
Is above the correct approach? If yes, Is this not making another trip to database? Is there a better approach?
You could add the PatchID to the SomeFilesViewModel along the PatchNumber. Otherwise there will be this extra query to the DB. On the other hand: this might create another possible problem, as the sent data don't have to be accurate and you'll need to check/validate it and that would be another trip to DB.
If you decide to stick with the extra query I would suggest rewriting it as following:
_context.Patch.Where(i => i.Number == someFileViewModel.PatchNumber).Select(i => i.PatchID).FirstOrDefault();
That way you get only the ID from the DB; assuming you don't need to work with other parts of your Patch object.

Entity Framework - Validation error on entity read at Azure

From yesterday i am struggling with that strange error. Localhost deploy works fine, but few hours after deploy on Azure i get
Validation failed for one or more entities. See 'EntityValidationErrors' property for more details.
It's happen when i enter to my controller registration action on fetching :
[AllowAnonymous]
public ActionResult Register()
{
Wallet stockMarketWallet = walletRepository.GetMarketWallet(); // here it comes
RegisterViewModel vm = new RegisterViewModel();
vm.UserStocks = new List<UserStockViewModel>();
foreach (UserStock stock in stockMarketWallet.OwnedStocks)
{
vm.UserStocks.Add(new UserStockViewModel {
StockId = stock.StockId,
Code = stock.Stock.Code
});
}
return View(vm);
}
Internal Error details says that UserApplications not unique username is rising ValidationError.
WalletRepository
public class WalletRepository : IWalletRepository
{
private ApplicationContext context;
public WalletRepository()
=> context = ApplicationContext.Create();
public Wallet GetMarketWallet()
{
string stockMarketUserName = ConfigurationManager.AppSettings["StockMarketUsername"];
return context.Wallets.FirstOrDefault(w => w.ApplicationUser.UserName.Equals(stockMarketUserName));
}
...
}
}
Wallet
public class Wallet
{
[Key, ForeignKey("ApplicationUser")]
public string WalletId { get; set; }
public decimal Founds { get; set; }
public virtual IList<UserStock> OwnedStocks { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
public Wallet()
{
OwnedStocks = new List<UserStock>();
}
...
}
ApplicationUser
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
return userIdentity;
}
public virtual Wallet Wallet { get; set; }
}
What is even stranger to me after cloning Azure database to localhost it works fine too.
According to your codes, I have developed a test demo on my computer, it works well.
I suggest you could create a new azure sql database and use its connection string directly in the local to test again.
More details about my test demo, you could refer to below codes:
IdentityModels.cs:
public class ApplicationUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser> manager)
{
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
// Add custom user claims here
return userIdentity;
}
public virtual Wallet Wallet { get; set; }
}
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DefaultConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
public DbSet<Wallet> Wallets { get; set; }
public DbSet<UserStock> UserStocks { get; set; }
}
Wallet.cs
public class Wallet
{
[Key, ForeignKey("ApplicationUser")]
public string WalletId { get; set; }
public decimal Founds { get; set; }
public virtual IList<UserStock> OwnedStocks { get; set; }
public virtual ApplicationUser ApplicationUser { get; set; }
public Wallet()
{
OwnedStocks = new List<UserStock>();
}
}
WalletRepository.cs
public class WalletRepository
{
public ApplicationDbContext context;
public WalletRepository() { context = ApplicationDbContext.Create(); }
public Wallet GetMarketWallet()
{
string stockMarketUserName = "The user name";
return context.Wallets.FirstOrDefault(w => w.ApplicationUser.UserName.Equals(stockMarketUserName));
}
}
HomeController:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
//Add test record
public ActionResult About()
{
ApplicationDbContext d1 = new ApplicationDbContext();
ApplicationUser user = d1.Users.FirstOrDefault(w => w.UserName.Equals("UserName"));
Wallet w1 = new Wallet();
w1.ApplicationUser = user;
w1.Founds = 300;
UserStock u1 = new UserStock();
u1.id = 1;
List<UserStock> l1 = new List<UserStock>();
l1.Add(u1);
w1.WalletId = user.Id;
d1.Wallets.Add(w1);
d1.SaveChanges();
ViewBag.Message = "Add Completed";
return View();
}
//Call the Repository to get the value
public ActionResult Contact()
{
WalletRepository walletRepository = new WalletRepository();
var result = walletRepository.GetMarketWallet();
ViewBag.Message = "WalletId : " + result.WalletId;
return View();
}
}
Result:
If this is still generate the error, please the details information about the error message.

CS0118 error in controller from model in asp.net [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 5 years ago.
Improve this question
I'm creating a database with the entity framework, I created the first entity as a carlot and the second car which will list the cars in the respective lots. I keep thinking something is wrong with my model ... here is following model
namespace CarLot.Models
{
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
public class CarModel : DbContext
{
public CarModel()
: base("name=CarModel")
{
}
// Add a DbSet for each entity type that you want to include in your model. For more information
// on configuring and using a Code First model, see http://go.microsoft.com/fwlink/?LinkId=390109.
public DbSet<CarLot> CarLots { get; set; }
public DbSet<Car> Cars { get; set; }
}
public class CarLot
{
//Primary Key
public int CarLotID { get; set; }
public string Name { get; set; }
public string Section { get; set; }
public virtual ICollection<Car> Cars { get; set; }
}
public class Car
{
public int CarId { get; set; }
public string Make { get; set; }
public string Model { get; set; }
public int Year { get; set; }
public int Price { get; set; }
public bool isNew { get; set; }
//foreign key
public int CarLotID { get; set; }
public virtual CarLot Carlot { get; set; }
}
}
I proceeded to scaffold the controller for Cars, that does not show any errors.
but not my carlot, this is the following CarLot file... its giving me the CS0118 error with CarLot as commented below, 6 following CarLot giving me the CS0118 which states "CarLot is a namespace but is used as a type"
sing System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web;
using System.Web.Mvc;
using CarLot.Models;
namespace CarLot.Controllers
{
public class CarLotsController : Controller
{
private CarModel db = new CarModel();
// GET: CarLots
public ActionResult Index()
{
return View(db.CarLots.ToList());
}
// GET: CarLots/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
// It is giving me the CS0118 error with the following CarLot
CarLot carLot = db.CarLots.Find(id);
if (carLot == null)
{
return HttpNotFound();
}
return View(carLot);
}
// GET: CarLots/Create
public ActionResult Create()
{
return View();
}
// POST: CarLots/Create
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "CarLotID,Name,Section")] CarLot carLot)
{
if (ModelState.IsValid)
{
db.CarLots.Add(carLot);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(carLot);
}
// GET: CarLots/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
CarLot carLot = db.CarLots.Find(id);
if (carLot == null)
{
return HttpNotFound();
}
return View(carLot);
}
// POST: CarLots/Edit/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "CarLotID,Name,Section")] CarLot carLot)
{
if (ModelState.IsValid)
{
db.Entry(carLot).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(carLot);
}
// GET: CarLots/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
CarLot carLot = db.CarLots.Find(id);
if (carLot == null)
{
return HttpNotFound();
}
return View(carLot);
}
// POST: CarLots/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
CarLot carLot = db.CarLots.Find(id);
db.CarLots.Remove(carLot);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}
namespace CarLot.Models
{
public class CarLot
{
The problem relates this code both namespace and class name is CarLot
Try changing one of them

While checking whether the user exists in the database "The entity type User is not part of the model for the current context"

While checking whether the user exists in the database, this happens "The entity type User is not part of the model for the current context".
"Sorry for my bad english"
This my Context:
public class UserContext : DbContext
{
public UserContext() :
base("PracticeDB")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<PracticeDB>().ToTable("Users");
}
public DbSet<User> Users { get; set; }
}
View model:
namespace Models.Models
{
public class LoginModel
{
[Required]
public string Name { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
}
}
Controller:
namespace Models.Controllers
{
public class AccountController : Controller
{
public ActionResult Login()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(LoginModel model)
{
if (ModelState.IsValid)
{
User user = null;
using (UserContext db = new UserContext())
{
user = db.Users.FirstOrDefault(u => u.Name == model.Name && u.Password == model.Password);
}
if (user != null)
{
FormsAuthentication.SetAuthCookie(model.Name, true);
return RedirectToAction("Users");
}
else
{
ModelState.AddModelError("", "Пользователя с таким логином и паролем нет");
}
}
return View(model);
}
}
}
enter image description here
I think this line in your UserContext:
modelBuilder.Entity<PracticeDB>().ToTable("Users");
Needs to change to:
modelBuilder.Entity<User>().ToTable("Users");
You need to tell the DbContext about the User model in OnModelCreating. Try changing the PracticeDB model to User in modelBuilder.Entity<PracticeDB>().ToTable("Users");.

Categories

Resources