Good morning everyone, I'm learning to use asp.net core in version 6 and I'm having problems saving a record to the database it shows the following error:
SqlException: Invalid object name 'VehiclePerson'.
From what I know, it is actually because it does not find the table in "VehiclePerson" although the connection is made, so I used Scaffolding to obtain the DB from Microsoft SSMS and I created the models and the Context file, so I don't think there are problems with the connection.
This is my VehiclePerson.cs file
using System.Collections.Generic;
namespace APITDCON.Models.QQGUAR01;
public partial class VehiclePerson
{
public string? EmpNumber { get; set; }
public string? Lastname { get; set; }
public string? Firstname { get; set; }
public string? Costcenter { get; set; }
public string? Department { get; set; }
public string? CredentNumber { get; set; }
public string? FromDate { get; set; }
public string? ToDate { get; set; }
public string? Rights { get; set; }
public int Id { get; set; }
}
This is my VehiclePerson.cs file
using Microsoft.EntityFrameworkCore;
using APITDCON.Models.QQGUAR01;
using Microsoft.IdentityModel.Tokens;
using System.Reflection;
using System;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
namespace APITDCON.Data
{
public class APITDCONContext : DbContext
{
public APITDCONContext(DbContextOptions<APITDCONContext> options) : base(options)
{
}
public DbSet<VehiclePerson> VehiclePerson { get; set; }
}
}
This is my VehiclePerson.cs file
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using APITDCON.Models.TANKFARM;
using APITDCON.Models;
using APITDCON.Data;
using System.Collections;
namespace APITDCON.Controllers
{
public class VehiclePersonController1 : Controller
{
private readonly APITDCONContext _apiTDCONContext;
public VehiclePersonController1(APITDCONContext apiTDCONContext)
{
_apiTDCONContext = apiTDCONContext;
}
[HttpGet]
public async Task<IActionResult> Index()
{
List<VehiclePerson> lista = new List<VehiclePerson>();
lista = GetAllDataDrivers();
return View(lista);
}
[HttpGet]
public IActionResult Add()
{
return View();
}
[HttpPost]
public IActionResult Add(VehiclePerson vehiclePersonRequest)
{
string mensaje = "";
var vehicleperson = new VehiclePerson()
{
EmpNumber = vehiclePersonRequest.EmpNumber,
Lastname = vehiclePersonRequest.Lastname,
Firstname = vehiclePersonRequest.Firstname,
Costcenter = vehiclePersonRequest.Costcenter,
Department = vehiclePersonRequest.Department,
CredentNumber = vehiclePersonRequest.CredentNumber,
FromDate = vehiclePersonRequest.FromDate,
ToDate = vehiclePersonRequest.ToDate,
Rights = vehiclePersonRequest.Rights
};
using (var db = new Models.QQGUAR01.Qqguar01Context())
{
var result = new List<VehiclePerson>();
result = (from data in db.VehiclePerson
select new VehiclePerson
{
EmpNumber = data.EmpNumber,
Lastname = data.Lastname,
Firstname = data.Firstname
}).ToList();
}
_apiTDCONContext.VehiclePerson.Add(vehicleperson);
_apiTDCONContext.SaveChanges();
return RedirectToAction("Add");
}
}
}
Database and table
Error
The table name defined in your database context is VehiclePerson, but your table name in the database is VEHICLE_PERSON, the two names do not match.
The easiest way is to change the name of the table VEHICLE_PERSON in the database to VehiclePerson, or change public DbSet<VehiclePerson> VehiclePerson { get; set; } to public DbSet<VehiclePerson> VEHICLE_PERSON { get; set; } in your context.
If you want to avoid similar situations in the future, you can use the following commands to migrate and update the database after adding Scaffolding:
Add-Migration InitialCreate
Update-Database
For more details on scaffolding and connecting to the database, you can refer to this official document.
By default EF will use entity name as table name so you can override it in multiple ways, for example using Table attribute:
[Table("VEHICLE_PERSON")]
public partial class VehiclePerson
{
}
Related
I'm connecting a MongoDB (Azure) with a MVC .NET C# project. The connection and object definition are working very good so far. My problem is when I try to add the method FIND() to return all the data in the object USER.
My Model:
using System;
using System.Collections.Generic;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using MongoDB.Driver;
using MongoDB.Driver.Builders;
namespace backendnet.Models
{
public class MongoCore
{
public class DB
{
static MongoClient Client = new MongoClient("mongodb://mydbconnect");
static public IMongoDatabase Database = Client.GetDatabase("mydb");
static public IMongoCollection<User> Users = Database.GetCollection<User>("users");
}
public class User
{
[BsonId]
public ObjectId Id { get; set; }
[BsonElement("email")]
public string Email { get; set; }
[BsonElement("password")]
public string Password { get; set; }
[BsonElement("name")]
public List<DimensionName> Name { get; set; }
[BsonElement("address")]
public List<DimensionAddress> Address { get; set; }
[BsonElement("permissions")]
public List<DimensionPermissions> Permissions { get; set; }
[BsonElement("status")]
public string Status { get; set; }
[BsonElement("created")]
public string Created { get; set; }
[BsonElement("updated")]
public string Updated { get; set; }
}
public class DimensionName
{
[BsonElement("first")]
public string First { get; set; }
[BsonElement("last")]
public string Last { get; set; }
}
public class DimensionAddress
{
[BsonElement("stree")]
public string Stree { get; set; }
[BsonElement("number")]
public string Number { get; set; }
[BsonElement("city")]
public string City { get; set; }
[BsonElement("state")]
public string State { get; set; }
[BsonElement("zipcode")]
public string Zipcode { get; set; }
[BsonElement("type")]
public string Type { get; set; }
}
public class DimensionPermissions
{
[BsonElement("list")]
public string List { get; set; }
[BsonElement("create")]
public string Create { get; set; }
[BsonElement("edit")]
public string Edit { get; set; }
[BsonElement("delete")]
public string Delete { get; set; }
}
}
}
My Controller:
using System;
using System.Collections.Generic;
using System.Web.Mvc;
using backendnet.Models;
using MongoDB.Bson;
namespace backendnet.Controllers
{
public class DashboardController : Controller
{
private string _viewFolder = "../Admin/Dashboard";
public ActionResult Index()
{
var results = new MongoCore.DB();
ViewData["ListPost"] = results.ToJson();
return View (_viewFolder);
}
}
}
My View partial:
<p>HERE: #ViewData["ListPost"]</p>
I get this:
HERE: { }
So I tried adding in the Model -> DB the method Find:
MongoCursor<User> cursor = Users.Find("Email" != "");
But always show an error:
Expression is always 'true' ["Email" != ""]
May anyone show me what I'm missing here?
I Don't See you calling MongoDB.Find()? I have pasted below my code I use for MongoDB C# driver in order to attain a record based on a key:value pair in my MongoDB database.
The Find or FindAsync method both require a BsonDocument Argument, which can be created using the Builders as seen below. Your filter can be empty, which would get all records since you are not filtering out anything.
Once you call the find method, you will be able to access the information using Lambda, or other query methods. You can see in my query i just need one record so i ask for FirstOrDefault. Hope this helps.
async Task<Document> IDal.GetRecordAsync(string key, string value)
{
try
{
if (Database == null) ((IDal)this).StartConnection();
var filter = Builders<BsonDocument>.Filter.Eq(key, value);
var cursor = await Collection.FindAsync(filter);
var bsondocument = cursor.FirstOrDefault();
return bsondocument == null ? null : _converter.ConvertBsonDocumentToDocument(bsondocument);
}
catch (Exception ex)
{
Console.WriteLine(ex);
return null;
}
}
public ActionResult GetUsers()
{
MongoServer objServer = MongoServer.Create("Server=localhost:27017");
MongoDatabase objDatabse = objServer.GetDatabase("DBName");
List UserDetails = objDatabse.GetCollection("Colletion_Name").FindAll().ToList();
return View(UserDetails);
}
I made a c#.NET WebAPI and it worked, but when I changed the model it stopped working and it gives me the following error message.
The model backing the 'ApiDbContext' context has changed since the
database was created. Consider using Code First Migrations to update
the database.
This is my code:
The Model (unchanged):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Test.Models
{
public class User
{
public int Id { get; set; }
public string Name { get; set; }
//public DateTime startTime { get; set; }
//public DateTime endTime { get; set; }
//public int Age { get; set; }
//public string Adress { get; set; }
}
}
The Model (changed):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace Test.Models
{
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime startTime { get; set; }
//public DateTime endTime { get; set; }
//public int Age { get; set; }
//public string Adress { get; set; }
}
}
The Controller (changed at updateUser):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using Test.DBA;
using Test.Models;
namespace Test.Controllers
{
public class UserAPIController : ApiController
{
ApiDbContext dbContext = null;
public UserAPIController()
{
dbContext = new ApiDbContext();
}
[HttpPost]
public IHttpActionResult InsertUser(User user)
{
dbContext.Users.Add(user);
dbContext.SaveChangesAsync();
return Ok(user.Name);
}
public IEnumerable<User> GetAllUser()
{
var list = dbContext.Users.ToList();
return list;
}
[HttpPost]
public IHttpActionResult DeleteUser(User user)
{
dbContext.Users.Remove(user);
dbContext.SaveChanges();
return Ok(user.Name);
}
[HttpGet]
public IHttpActionResult ViewUser(int id)
{
var student = dbContext.Users.Find(id);
return Ok(student);
}
[HttpPost]
public IHttpActionResult UpdateUser(User user)
{
User std = dbContext.Users.Find(user.Id);
std.Name = user.Name;
std.startTime = user.startTime;
//std.endTime = user.endTime;
//std.Age = user.Age;
//std.Adress = user.Adress;
dbContext.Entry(std).State = System.Data.Entity.EntityState.Modified;
dbContext.SaveChangesAsync();
return Ok();
}
}
}
DBContext:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using Test.Models;
namespace Test.DBA
{
public class ApiDbContext :DbContext
{
public ApiDbContext() : base("Connection")
{
}
public DbSet<User> Users { get; set; }
}
}
Connection string:
<connectionStrings>
<add name ="Connection" connectionString="Data Source=.\SQLExpress;Initial Catalog=k;Integrated Security=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
Type Enable-Migrations in package-manager-console, after type add-migration, set name, then type update-database
https://msdn.microsoft.com/en-ca/data/jj591621(v=vs.113).aspx
Enable-Migrations: Enables the migration in your project by creating a Configuration class.
Add-Migration: Creates a new migration class as per specified name with the Up() and Down() methods.
Update-Database: Executes the last migration file created by the Add-Migration command and applies changes to the database schema.
more Details:
https://www.entityframeworktutorial.net/code-first/code-based-migration-in-code-first.aspx
Here is my Model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace TheFoody.Models
{
public class ManageViewModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Photo { get; set; }
public string Address { get; set; }
public string City { get; set; }
public int PostCode { get; set; }
public string District { get; set; }
public string UserType { get; set; }
public string Status { get; set; }
}
}
Here is my Context
namespace TheFoody.DataAccess
{
using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
public partial class TheFoodyContext : DbContext
{
public TheFoodyContext()
: base("name=TheFoodyContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Menu> Menus { get; set; }
public virtual DbSet<User> Users { get; set; }
public virtual DbSet<Category> Categories { get; set; }
public virtual DbSet<Restaurant> Restaurants { get; set; }
public virtual DbSet<Restaurant_Type> Restaurant_Type { get; set; }
}
}
Here is My Controller
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using TheFoody.DataAccess;
using TheFoody.Models;
namespace TheFoody.Controllers
{
public class ManageController : Controller
{
public ActionResult Manage()
{
return View();
}
[HttpPost]
public ActionResult Manage(ManageViewModel manageviewmodel)
{
TheFoodyContext db = new TheFoodyContext();
ManageViewModel user_to_update = db.Users.SingleOrDefault(s => s.email == manageviewmodel.Email);
return View(manageviewmodel);
}
}
}
But In here when i'm trying to code this part "ManageViewModel user_to_update = db.Users.SingleOrDefault(s => s.email == manageviewmodel.Email);" It will give me highlighted error called "Cannot implicitly convert type 'TheFoody.DataAccess.User' to 'TheFoody.Models.ManageViewModel'"
I'm very new to this environment and i don't know why this error coming like these.
db.Users is a DbSet<TheFoody.DataAccess.User>, and the SingleOrDefault() returns one such a user, or null when no user was found by that email address.
An instance of that class cannot be implicitly converted to the requested ManageViewModel, you need to map it:
DataAccess.User user = db.Users.SingleOrDefault(...);
if (user == null)
{
// show error page telling that the POSTed email address is not known
}
ManageViewModel user_to_update = new ManageViewModel
{
FirstName = user.FirstName,
LastName = user.LastName,
// ...
}
return View(user_to_update);
You can use AutoMapper to do the mapping in a more convenient way.
Although, it seems like you want to update the database with the model sent through POST, then you need to change the logic: you need to assign the user's properties from the received manageviewmodel:
// read from database
DataAccess.User user = db.Users.SingleOrDefault(...);
if (user == null)
{
// show error page telling that the POSTed email address is not known
}
// update from POST
user.FirstName = manageviewmodel.FirstName;
user.LastName = manageviewmodel.LastName;
// ...
// persist to database
db.SaveChanges();
That's because you cannot directly cast a type of User to ManageViewModel
You can fix the issue by assigning the result of the query to a type User and then iterate the properties of the User type and assign them to the relevant property of a ManageViewModel type.
Example:
User user_to_update = db.Users.SingleOrDefault(s => s.email == manageviewmodel.Email);
if (user != null)
{
var manageViewModel = new ManageViewModel()
manageViewModel.FirstName = user.FirstName;
manageViewModel.LastName = user.LastName;
}
else {
//Manage null exception here
}
...And so on
I have a DBContext "StatusDBContext", a Model "Status_T" with some(n) properties and a corresponding ViewModel "Status" with few of the Model properties. I am using Entity Framework with code first from database.
DBContext:
namespace xxx.Areas.SysParam.Models
{
using System;
using System.Data.Entity;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
public partial class StatusDbContext : DbContext
{
public StatusDbContext()
: base("name=xxxConnectionString")
{
}
public virtual DbSet<STATUS_T> STATUS_T { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<STATUS_T>().ToTable("STATUS_T");
}
}
}
Model:
namespace xxx.Areas.SysParam.Models
{
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.Spatial;
[Table("STATUS_T")]
public partial class STATUS_T
{
[Key]
[Column(Order = 0)]
[StringLength(35)]
public string TYPE { get; set; }
[Key]
[Column(Order = 1)]
public byte STATUS { get; set; }
[StringLength(30)]
public string DESCRIPTION { get; set; }
[Key]
[Column(Order = 2)]
[StringLength(2)]
public string LANG_CODE { get; set; }
public DateTime UPD_DTIME { get; set; }
public DateTime? DELETE_DTIME { get; set; }
public short? VER_NO { get; set; }
[StringLength(1)]
public string STAT_USE { get; set; }
}
}
View Model:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using xxx.Areas.SysParam.Models;
namespace xxx.Areas.SysParam.ViewModels
{
public class Status
{
[Display(Name = "Status ID")]
public byte STATUS { get; set; }
[Display(Name = "Description")]
public string DESCRIPTION { get; set; }
[Display(Name = "Type")]
public string TYPE { get; set; }
[Display(Name = "In Use")]
public string STAT_USE { get; set; }
}
}
Before introducing ViewModel the Controller looked like:
public ActionResult StatusView()
{
List<Models.STATUS_T> StatusList = new List<Models.STATUS_T>();
using (var status = new Models.StatusDbContext())
{
StatusList = Status.STATUS_T.ToList();
}
return View(StatusList);
}
Now I have two questions.
1) As I googled about Model, ViewModel and DataAnnotations its somewhat clear that DataAnnotations should be added to ViewModel but in Code First from Existing DB the Models are generated with few DataAnnotations so what will be the best practice here, to copy properties from Model to ViewModel and add more DataAnnotations whenever required?
2) How to replace Model with ViewModel in Controller code?
Help will be appreciated. Thanks!!!
Updated: Controller:
public ActionResult DWPStatusView()
{
var DWPStatusList = new List<ViewModels.DWPStatus>();
using (var DWPStatus = new Models.DWPStatusDbContext())
{
DWPStatusList = DWPStatus.DWP_STATUS_T.ToList().Select(p => new ViewModels.DWPStatus(p)).ToList();
}
return View(DWPStatusList);
}
1.Yes, best practise is to create separate view model class and copy there necessary properties from DB model, because:
may happen that DB model have unwanted properties for view
view model may need additional properties and adding them to DB model
is not good practise
View model usually have validation data annotations attributes, so better keep them also separate from DB annotations.
2.
public ActionResult StatusView()
{
var statusList = new List<ViewModels.Status>();
using (var status = new Models.StatusDbContext())
{
statusList = Status.STATUS_T.ToList().Select(p => new ViewModels.Status {
Property1 = p.Property1,
Property2 = p.Property2,
...
}).ToList();
}
return View(statusList);
}
You can place property mapping into view model constructor, then selecting data will look next:
statusList = Status.STATUS_T.ToList().Select(p => new ViewModels.Status(p)).ToList();
Update: and view model:
public class Status
{
public Status(){}
public Status(Models.STATUS_T model)
{
//here comes mapping
}
....
}
In my controller i am creating a subcategory object and giving that object a reference to the category it belongs to. Everything works fine when i debug the site but when i load the list of objects from my entityframework db all the category object references are removed. the rest persists. anybody got an idea why this happens ?
Controller:
[Authorize(Roles = "administrator")]
[HttpPost]
public ActionResult Create(CategoryViewModel viewmodel, HttpPostedFileBase Icon)
{
SubCategory subcategory = new SubCategory();
Category category = categorycontroller.getCategoryByName(viewmodel.SelectedValue);
viewmodel.subcategory.Category = category;
subcategory = viewmodel.subcategory;
category.Subcategories.Add(subcategory);
if (Icon != null && Icon.ContentLength > 0)
{
var fileName = Path.GetFileName(Icon.FileName);
var path = Path.Combine(Server.MapPath("../../Content/icons/"), fileName);
Icon.SaveAs(path);
subcategory.Icon = fileName;
}
if (ModelState.IsValid)
{
subcategorydb.categories.Attach(category);
subcategorydb.subcategories.Add(subcategory);
subcategorydb.SaveChanges();
return RedirectToAction("Index");
}
return View(subcategory);
}
and this is my viewmodel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using System.Web.Mvc;
using SkyLearn.Areas.Categories.Controllers;
namespace SkyLearn.Areas.Categories.Models
{
public class CategoryViewModel
{
public List<SelectListItem> PossibleValues { get; set; }
public string SelectedValue { get; set; }
public SubCategory subcategory { get; set; }
public CategoryController categorycontroller;
public CategoryViewModel()
{
PossibleValues = new List<SelectListItem>();
}
}
}
And here is my Category and SubCategory class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
namespace SkyLearn.Areas.Categories.Models
{
public class Category
{
public int ID { get; set; }
public string Title { get; set; }
public string Icon { get; set; }
public string Description { get; set; }
public List<SubCategory> Subcategories;
public Category()
{
Subcategories = new List<SubCategory>();
}
}
public class CategoryDBContext : DbContext
{
public DbSet<Category> categories { get; set; }
public DbSet<SubCategory> subcategories { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using SkyLearn.Areas.Categories.Controllers;
namespace SkyLearn.Areas.Categories.Models
{
public class SubCategory
{
public int ID { get; set; }
public string Title { get; set; }
public string Icon { get; set; }
public string Description { get; set; }
public int CategoryID { get; set; }
public Category Category { get; set; }
}
public class SubCategoryDBContext : DbContext
{
public DbSet<SubCategory> subcategories { get; set; }
public DbSet<Category> categories { get; set; }
}
}
i have searched many sites for info on this problem but couldnt find much of help. Anybody here able to identify my problem?
as seen on this screenshot the object is correctly referenced by all means. but when i load the data next time the object reference has disapeared. all other attributes are still there and saved as they should:
thanks AronChan
//// Update ////
I am now getting the following error:
A foreign key value cannot be inserted because a corresponding primary
key value does not exist. [ Foreign key constraint name =
SubCategory_Category ]
Your category object won't get saved because it is not attached to the DbContext that you add the subcategory to. The subcategory might know about the reference but the category won't. If there is a lookup table (which there must be if its many to many) I don't see how that record would be saved. Try attaching the category, adding the subcategory and then saving. Personally I have always set up the many-to-many look up tables as their own entity. It is a little easier to visualize what is actually happening as opposed to giving all control to EF.
Also, if you are using code first, make sure your EntityConfigurations are correct. Try running the EdmxWriter over your context to make sure the data model looks exactly how you want it to.