我需要将多种技能(这些技能是动态地来自技能表)储存在雇员表技能栏中
原标题:I need to store multiple Skills (which are coming from Skill table dynamically) in Skill column in Employee table
In ASP.NET Core 8 MVC, rest of the form is perfect but having issue in Skill column in Employee table. I want to store multiple skills using checkbox while submitting Employee form.
I get an error while submitting:
SqlException: Invalid object name EmployeeSkills .
ApplicationDbContext:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions options) : base(options)
{
}
// Model
public DbSet
Skill { get; set; }
public DbSet State { get; set; }
public DbSet City { get; set; }
public DbSet Employee { get; set; }
public DbSet EmployeeSkills { get; set; }
// ViewModel
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// modelBuilder.Entity().HasNoKey();
modelBuilder.Entity()
.HasKey(es => new { es.EmployeeId, es.SkillId });
modelBuilder.Entity()
.HasOne(es => es.Employee)
.WithMany(e => e.EmployeeSkills)
.HasForeignKey(es => es.EmployeeId);
modelBuilder.Entity()
.HasOne(es => es.Skill)
.WithMany(s => s.EmployeeSkills)
.HasForeignKey(es => es.SkillId);
}
}
Skill model class:
public class Skill
{
[Key]
public int SkillId { get; set; }
[Required]
public string? SkillName { get; set; }
// Navigation properties
public ICollection EmployeeSkills { get; set; } = new List();
}
Employee table definition:
CREATE TABLE [dbo].[Employee]
(
[EmployeeId] INT IDENTITY (202401, 1) NOT NULL,
[Name] NVARCHAR(50) NULL,
[Email] NVARCHAR(50) NULL,
[Mobile] NVARCHAR(50) NULL,
[StateId] INT NULL,
[CityId] INT NULL,
[Address] NVARCHAR(MAX) NULL,
[Gender] NVARCHAR(50) NULL,
[Skill] NVARCHAR(MAX) NULL,
[Profile] NVARCHAR(MAX) NULL,
CONSTRAINT [PK_Employee]
PRIMARY KEY CLUSTERED ([EmployeeId] ASC),
CONSTRAINT [FK_Employee_City]
FOREIGN KEY ([CityId]) REFERENCES [dbo].[City] ([CityId]),
CONSTRAINT [FK_Employee_State]
FOREIGN KEY ([StateId]) REFERENCES [dbo].[State] ([StateId])
);
Employee model class:
public class Employee
{
[Key]
public int EmployeeId { get; set; }
[Required(ErrorMessage = "Name is required")]
public string? Name { get; set; }
[Required(ErrorMessage = "Email is required")]
[EmailAddress(ErrorMessage = "Invalid email")]
public string? Email { get; set; }
[Required(ErrorMessage = "Mobile is required")]
[MaxLength(10, ErrorMessage = "Mobile should be 10 digits")]
[MinLength(10, ErrorMessage = "Mobile should be 10 digits")]
public string? Mobile { get; set; }
[Required(ErrorMessage = "State is required")]
public int StateId { get; set; }
[Required(ErrorMessage = "City is required")]
public int CityId { get; set; }
[Required(ErrorMessage = "Address is required")]
public string? Address { get; set; }
[Required(ErrorMessage = "Gender is required")]
public string? Gender { get; set; }
[Required(ErrorMessage = "Skill is required")]
public string? Profile { get; set; }
// Navigation properties
[BindNever]
public State? State { get; set; }
[BindNever]
public City? City { get; set; }
public ICollection EmployeeSkills { get; set; } = new List();
}
EmployeeViewModel:
public class EmployeeViewModel
{
[Required (ErrorMessage = "Name is required")]
public string? Name { get; set; }
[Required(ErrorMessage = "Email is required")]
[EmailAddress(ErrorMessage = "Invalid email")]
public string? Email { get; set; }
[Required(ErrorMessage = "Mobile is required")]
[MaxLength(10, ErrorMessage = "Mobile should be 10 digits")]
[MinLength(10, ErrorMessage = "Mobile should be 10 digits")]
public string? Mobile { get; set; }
[Required(ErrorMessage = "State is required")]
public int? StateId { get; set; }
[Required(ErrorMessage = "City is required")]
public int? CityId { get; set; }
[Required(ErrorMessage = "Address is required")]
public string? Address { get; set; }
[Required(ErrorMessage = "Gender is required")]
public string? Gender { get; set; }
public List SelectedSkillIds { get; set; } = new List();
public string? Profile { get; set; }
public SelectList? States { get; set; }
public SelectList? Cities { get; set; }
public SelectList? Skills { get; set; }
}
EmployeeSkill table definition:
CREATE TABLE [dbo].[EmployeeSkill]
(
[EmployeeId] INT NOT NULL,
[SkillId] INT NOT NULL,
CONSTRAINT [PK_EmployeeSkill]
PRIMARY KEY CLUSTERED ([EmployeeId] ASC, [SkillId] ASC),
CONSTRAINT [FK_EmployeeSkill_Employee]
FOREIGN KEY ([EmployeeId]) REFERENCES [dbo].[Employee] ([EmployeeId]),
CONSTRAINT [FK_EmployeeSkill_Skill]
FOREIGN KEY ([SkillId]) REFERENCES [dbo].[Skill] ([SkillId])
);
EmployeeSkill model class:
public class EmployeeSkill
{
public int EmployeeId { get; set; }
public Employee Employee { get; set; }
public int SkillId { get; set; }
public Skill Skill { get; set; }
}
EmployeeController:
public class EmployeeController : Controller
{
private readonly ApplicationDbContext _context;
private readonly IWebHostEnvironment _hostEnvironment;
public EmployeeController(ApplicationDbContext context, IWebHostEnvironment hostEnvironment)
{
_context = context;
_hostEnvironment = hostEnvironment;
}
public IActionResult Index()
{
return View();
}
// Employee/Create
[HttpGet]
public IActionResult Create()
{
var employeeViewModel = new EmployeeViewModel
{
States = new SelectList(_context.State.ToList(), "StateId", "StateName"),
Cities = new SelectList(Enumerable.Empty(), "CityId", "CityName"),
Skills = new SelectList(_context.Skill.ToList(), "SkillId", "SkillName")
};
return View(employeeViewModel);
}
[HttpPost]
public async Task Create(EmployeeViewModel employeeViewModel, IFormFile profileFile)
{
// If a state is selected, populate the cities for that state
if (employeeViewModel.StateId.HasValue)
{
employeeViewModel.Cities = new SelectList(_context.City
.Where(c => c.StateId == employeeViewModel.StateId).ToList(), "CityId", "CityName");
}
else
{
employeeViewModel.Cities = new SelectList(Enumerable.Empty(), "CityId", "CityName");
}
// Re-populate the states dropdown for the view
employeeViewModel.States = new SelectList(_context.State.ToList(), "StateId", "StateName");
// Re-populate the skills for the view
employeeViewModel.Skills = new SelectList(_context.Skill.ToList(), "SkillId", "SkillName");
if (ModelState.IsValid)
{
var existEmployee = await _context.Employee.FirstOrDefaultAsync(e => e.Email == employeeViewModel.Email);
if (existEmployee != null)
{
ModelState.AddModelError("Email", "Email already exist");
employeeViewModel.States = new SelectList(_context.State.ToList(), "StateId", "StateName");
employeeViewModel.Cities = new SelectList(_context.City.Where(c => c.StateId == employeeViewModel.StateId).ToList(), "CityId", "CityName");
employeeViewModel.States = new SelectList(_context.Skill.ToList(), "SkillId", "SkillName");
return View(employeeViewModel);
}
// Handle file upload
if (profileFile != null)
{
string uploadDir = Path.Combine(_hostEnvironment.WebRootPath, "uploads");
Directory.CreateDirectory(uploadDir);
string fileName = Guid.NewGuid().ToString() + Path.GetExtension(profileFile.FileName);
string filePath = Path.Combine(uploadDir, fileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await profileFile.CopyToAsync(fileStream);
}
employeeViewModel.Profile = fileName; // Store the file name or path
}
var employee = new Employee
{
Name = employeeViewModel.Name,
Email = employeeViewModel.Email,
Mobile = employeeViewModel.Mobile,
StateId = employeeViewModel.StateId.Value,
CityId = employeeViewModel.CityId.Value,
Address = employeeViewModel.Address,
Gender = employeeViewModel.Gender,
Profile = employeeViewModel.Profile
};
foreach (var skillId in employeeViewModel.SelectedSkillIds)
{
employee.EmployeeSkills.Add(new EmployeeSkill { SkillId = skillId });
}
_context.Employee.Add(employee);
await _context.SaveChangesAsync();
return RedirectToAction("Index");
}
// If model is invalid, reload the form with existing states and cities
employeeViewModel.States = new SelectList(_context.State.ToList(), "StateId", "StateName");
employeeViewModel.Cities = new SelectList(_context.City.Where(c => c.StateId == employeeViewModel.StateId).ToList(), "CityId", "CityName");
employeeViewModel.Skills = new SelectList(_context.Skill.ToList(), "SkillId", "SkillName");
return View(employeeViewModel);
}
}
Create.cshtml view of EmployeeController:
@model Candidate.ViewModel.EmployeeViewModel
@{
ViewData["Title"] = "Employee Create";
}
EMPLOYEE CREATE
I tried without relationship between Employee and Skill tables, but while submitting it will match and verify the SkillId as want to store multiple Skill it will not work.
I want to store multiple Skill while submitting
问题回答
From the code you provided, we can see that by default, EF will generate the table EmployeeSkills:
Therefore, EmployeeSkills should be configured in the database instead of EmployeeSkill. The table definition is as follows:
CREATE TABLE [dbo].[EmployeeSkills] (
[EmployeeId] INT NOT NULL,
[SkillId] INT NOT NULL,
CONSTRAINT [PK_EmployeeSkills] PRIMARY KEY CLUSTERED ([EmployeeId] ASC, [SkillId] ASC),
CONSTRAINT [FK_EmployeeSkills_Employee_EmployeeId] FOREIGN KEY ([EmployeeId]) REFERENCES [dbo].[Employee] ([EmployeeId]) ON DELETE CASCADE,
CONSTRAINT [FK_EmployeeSkills_Skill_SkillId] FOREIGN KEY ([SkillId]) REFERENCES [dbo].[Skill] ([SkillId]) ON DELETE CASCADE
);
When I insert related data:
相关问题
What is the use of `default` keyword in C#?
What is the use of default keyword in C#?
Is it introduced in C# 3.0 ?
Anyone feel like passing it forward?
I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs.
...
NSArray s, Primitive types and Boxing Oh My!
I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits.
Now here s the question: I feel really inclined to create some type of ...
C# Marshal / Pinvoke CBitmap?
I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class.
My import looks like this:
[DllImport(@"test.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr ...
ADO.NET Entity Framework Association of Entities by Value Range
I have two EF entities. One has a property called HouseNumber. The other has two properties, one called StartHouseNumber and one called EndHouseNumber.
I want to create a many to many association ...
How to Use Ghostscript DLL to convert PDF to PDF/A
How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...
What is the most efficient keyvalue pair for ordering?
Since I cannot order my dictionary, what is the best way of going about taking key value pairs and also maintaing an index?
Linqy no matchy
Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control.
...