Настройте отношения «многие ко многим» в ASP.NET Core MVC и Entity Framework для

Я пытаюсь настроить отношения «многие ко многим» между двумя таблицами, Employee и Project.

Один Employee может участвовать во многих проектах, а над одним проектом может работать много Employees. Поэтому я создал два класса моделей Employee и Project и добавил таблицу Employee_Project.

Это три моих модельных класса:

namespace WebApp2.Models
{
    public class Employee
    {
        [Key]
        public int Emp_Id { get; set; }
        public string Emp_Name { get; set; }
        public string Emp_Email { get; set; }
        public string Emp_Mobile { get; set; }

        public virtual ICollection<Employee_Project> Employee_Projects { get; set; }
    }

    public class Project
    {
        [Key]
        public int Proj_Id { get; set; }
        public string Proj_Name { get; set; }
        public string Project_Details { get; set; }
        public virtual ICollection<Employee_Project> Employee_Projects { get; set; }
    }

    public class Employee_Project
    {
        [Key]
        [Column(Order =1)]
        public int Emp_Id { get; set; }
        [Key]
        [Column(Order = 2)]
        public int Proj_Id { get; set; }

        public virtual Employee Employee { get; set; }
        public virtual Project Project { get; set; }
    }
}

Затем я добавил этот класс DbContext:

namespace WebApp2.Data
{
    public class MyDbContext:DbContext
    {
        public MyDbContext(DbContextOptions<MyDbContext> option):base(option)
        {
        }

        public DbSet<Employee> Employees { get; set; }
        public DbSet<Project> Projects { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Employee_Project>().HasKey(pt => new { pt.Proj_Id, pt.Emp_Id });

            modelBuilder.Entity<Employee_Project>()
                        .HasOne(pt => pt.Employee)
                        .WithMany(pt => pt.Employee_Projects)
                        .HasForeignKey(p => p.Emp_Id);

            modelBuilder.Entity<Employee_Project>()
                        .HasOne(pt => pt.Project)
                        .WithMany(pt => pt.Employee_Projects)
                        .HasForeignKey(p => p.Proj_Id);
        }

        public DbSet<Employee_Project> Employee_Projects { get; set; }
    }
}

Я создал после этого три контроллера

public class ProjectController : Controller
    {
        private readonly MyDbContext _context;

        public ProjectController(MyDbContext context)
        {
            _context = context;
        }
        public IActionResult Index()
        {
            return View(_context.projects.ToList());
        }

        public IActionResult Create()
        {
            return View();
        }
        [HttpPost]
        public IActionResult Create(Project project)
        {
            _context.projects.Add(project);
            _context.SaveChanges();
            return RedirectToAction("Index");
        }
    }




public class EmployeeController : Controller
    {
        private readonly MyDbContext _context;

        public EmployeeController(MyDbContext context)
        {
            _context = context;
        }
        public IActionResult Index()
        {
            return View(_context.Employees.ToList());
        }

        public IActionResult Create()
        {
            return View();
        }
        [HttpPost]
        public IActionResult Create(Employee employee)
        {
             _context.Employees.Add(employee);
            _context.SaveChanges(); 
            return RedirectToAction("Index");
        }
    }





public class Emp_ProjController : Controller
    {
        private readonly MyDbContext _DbContext;

        public Emp_ProjController(MyDbContext DbContext)
        {
            _DbContext = DbContext;
        }
        public IActionResult Index()
        {
            return View(_DbContext.Employee_Projects.ToList());
        }

        
        public IActionResult Create()
        {
            ViewBag.emp=_DbContext.Employees.ToList();
            ViewBag.pro=_DbContext.projects.ToList();
            return View();
        }

        [HttpPost]
        public IActionResult Create(int empid, int [] projIds)
        {
            foreach (var item in projIds)
            {
                Employee_Project emp = new Employee_Project();
                emp.Emp_Id = empid;
                emp.Proj_Id = item;
                _DbContext.Employee_Projects.Add(emp);
                _DbContext.SaveChanges();

            }
            return RedirectToAction("Index");
            
            
        }

    }


После этого foreach Controllers я сделал представление для метода Index и Create

Эмп_Продж

// просмотр индекса

@model IEnumerable<WebApp2.Models.Employee_Project>

@{
    ViewData["Title"] = "Index";
}

<h1>Index</h1>

<p>
    <a asp-action = "Create">Create New</a>
</p>
<table class = "table">
    <thead>
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Employee.Emp_Name)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Project.Proj_Name)
            </th>
            <th></th>
        </tr>
    </thead>
    <tbody>
@foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Employee.Emp_Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Project.Proj_Name)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
            </td>
        </tr>
}
    </tbody>
</table>

//view Create

<h2>Create</h2>

<form method = "post">
    <div>
        <label>Employee Name</label>
        @Html.DropDownList("empid", new SelectList(ViewBag.emp, "Emp_Id","Emp_Email"),"Select Employee")
    </div>
    <div>
        <label>Select Project</label>
       @* @Html.DropDownList("proid", new SelectList(ViewBag.pro, "Proj_Id","Proj_Name"),"Select Project")*@

        <ul>
            @foreach(var item in ViewBag.pro )
            {
                <li>
                    <input type = "checkbox" name = "projIds" value = "@item.Proj_Id">@item.Proj_Name
                </li>
            }
        </ul>

        <input  type = "submit" value = "SaveData"/>
        
    </div>
</form>



У меня нет проблем с сотрудником и проектом, я обнаружил проблему, когда хочу создать элемент Emp_Proj. введите здесь описание изображения Мне всегда выдает такую ​​ошибку:

SqlException: нарушение ограничения PRIMARY KEY «PK_Employee_Projects». Не удается вставить повторяющийся ключ в объект «dbo.Employee_Projects». Повторяющееся значение ключа: (1, 1). Инструкция прекращена.

введите здесь описание изображения

Может кто-нибудь, пожалуйста, помогите мне найти проблему? Заранее спасибо.

Я пытаюсь найти проблему, и я ценю некоторую помощь.

Исключение объясняет само себя, не так ли? Вы не проверяете, существует ли комбинация уже в базе данных.

Gert Arnold 08.02.2023 09:51

Возможно, проверьте порядок ключей в modelBuilder.Entity<Employee_Project>().HasKey(pt => new { pt.Proj_Id, pt.Emp_Id });

ValNik 08.02.2023 10:19

@ValNik, я не понимаю порядок ключей

user95 08.02.2023 11:32

В Employee_Project: определенный порядок столбцов Emp_id = 1, порядок столбцов Proj_Id = 2. И затем вы используете новый {Proj_id, Emp_id}

ValNik 08.02.2023 12:38
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
66
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Сообщение об ошибке показывает причину возникновения этого исключения: база данных уже содержит эту запись, вы не можете вставлять повторяющиеся данные. Вам просто нужно проверить, существует ли он уже в базе данных, прежде чем вставлять данные. Пожалуйста, обратитесь к этой простой демонстрации.

[HttpPost]
        public IActionResult Create(int empid, int[] projIds)
        {
            foreach (var item in projIds)
            {
                //check if the database already has this record
                var empdb = _DbContext.Employee_Projects.Where(x => x.Emp_Id == empid && x.Proj_Id == item).FirstOrDefault();

                if (empdb==null)
                {
                    Employee_Project emp = new Employee_Project();
                    emp.Emp_Id = empid;
                    emp.Proj_Id = item;
                    _DbContext.Employee_Projects.Add(emp);
                }
                
           
            }
            _DbContext.SaveChanges();
            return RedirectToAction("Index");
        }

Привет, Xinran Shen Большое спасибо, все работает правильно, я вижу все свои записи в базе данных, но не вижу данных в таблице, таблица пуста. На странице индекса Emp_ProjController я хочу увидеть имя сотрудника и название проекта, но оно пустое.

user95 09.02.2023 11:10

@ user95 что вы подразумеваете под «записями»? вы пытаетесь засеять данные? как вы пытаетесь вставить данные? ваша проблема с пустой таблицей? или имена сотрудников и проектов не представлены в качестве столбцов для таблицы ассоциаций? потому что это совсем другая тема.

Mephisto 09.02.2023 11:20

вам, вероятно, следует задать новый вопрос, так как ваша проблема исчезла.

Mephisto 09.02.2023 11:21

когда я добавил некоторых сотрудников и проекты, он работает, но я не вижу данные в индексе представления, но когда я открыл свою таблицу Employee_Projects на сервере sql, я вижу все записи. Могу ли я отправить другие изображения?

user95 09.02.2023 11:35

Во-первых, попробуйте полностью удалить объект «Employee_Project» и посмотрите, сможет ли EF Core создать его автоматически. EF Core должен иметь возможность автоматически создавать ассоциативную таблицу, если для двух сущностей заданы два навигационных свойства. Обратите внимание, что навигационные свойства двух объектов должны ссылаться друг на друга. вот так;

в Сотрудник;

public virtual ICollection<Project> Projects { get; set; }

и в проекте;

public virtual ICollection<Employee> Employees { get; set; }

Если это не сработает, измените свой класс Employee_Project следующим образом;

public class Employee_Project
    {
        [Key]
        [Column(Order =1)]
        public int EmployeeId { get; set; }
        [Key]
        [Column(Order = 2)]
        public int ProjectId { get; set; }

        public virtual Employee Employee { get; set; }
        public virtual Project Project { get; set; }
    }

Возможно, проблема заключалась в именовании столбцов.

Другие вопросы по теме

Похожие вопросы

Как сохранить отключенный игровой объект?
AVAudioPlayer: ожидание окончания воспроизведения звука
Как избежать взаимоблокировки при использовании одноэлементного Http-клиента в приложении Winforms
Элемент уже является дочерним элементом другого элемента при добавлении разных изображений в элемент пользовательского интерфейса
Как вернуть описание перечисления вместо имени в API через файл Dto в С#?
Использование '||' логический оператор ИЛИ для сравнения строк
Как сделать вложенный список из элементов одного уровня на основе начального текста
Как получить свойства из списка объектов, привязанных к CarouselView в .NET MAUI
Замаскируйте любой 15-значный или 16-значный номер кредитной карты в строке, заменив на X, кроме последних 4 цифр. Сложная головоломка с регулярными выражениями в C#
Почему я вижу, что «тип или пространство имен «HtmlIframe» не существует в пространстве имен «System.Web.UI.HtmlControls» (вам не хватает ссылки на сборку?)»