Ошибка - оператор INSERT конфликтует с ограничением FOREIGN KEY - PullRequest
0 голосов
/ 11 июня 2018

При использовании EF Code First миграции я получаю ошибку при СОЗДАНИИ Предмета с кодом в базе данных.

Я проверил несколько тестов на stackoverflow, похожих на мой вопрос, но они не помогают мне решить мою проблему.Я не использую автоматические миграции.

Я следовал этому руководству, http://mahedee.net/cascading-dropdown-list-in-asp-net-mvc-a-sample-demonstration/#comment-17847 для создания каскадных выпадающих списков для MainCategories / SubCategories, и он отлично работает в моем списке, но когда я иду, чтобы создать элемент, я получаю следующую ошибку:

Оператор INSERT вступил в конфликт с ограничением FOREIGN KEY «FK_dbo.Fabrics_dbo.MainCategories_MainCategoryId».Конфликт произошел в базе данных «MyFabricStashAppDb», таблице «dbo.MainCategories», столбце «MainCategoryId».Оператор был прерван.

Мои модели следующие: My MainCategory.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MyFabricStashApp.Models
{
    public class MainCategory
    {
        public int MainCategoryId { get; set; }
        public string Name { get; set; }
        public List<SubCategory1> SubCategories1 { get; set; }

    }
}

Моя подкатегория1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;

namespace MyFabricStashApp.Models
{
    public class SubCategory1
    {
        public int SubCategory1Id { get; set; }
        public string Name { get; set; }
        public int MainCategoryId { get; set; }
        public virtual MainCategory MainCategory { get; set; }

    }
}

Моя ткань.cs (Элемент класса)

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Web;

namespace MyFabricStashApp.Models
{
    public class Fabric
    {
        public int FabricId { get; set; } //Item Number

        public int MainCategoryId { get; set; }
        public virtual MainCategory MainCategory { get; set; }

        public int SubCategory1Id { get; set; }
        public virtual SubCategory1 SubCategory1 { get; set; }
        public string Name { get; set; }
        public string ImagePath { get; set; }
        public string Location { get; set; }
        public string Type { get; set; } //Knit, Woven, Voile, Interfacing, Denim, Suiting, etc.
        public string Weight { get; set; }//Lightweight, Medium, Heavy
        public string Content { get; set; }//Cotton, Polyester, Nylon, etc.
        public string Design { get; set; }//Marvel Comics, Amy Butler, etc.
        public string Brand { get; set; } //Springs Creative Products, Free Spirit, Robert Kaufman, etc.
        public double Quantity { get; set; }//.25 yd, .50 yd, .75 yd, 1.0 yd, etc.
        public int Width { get; set; }// in inches, ie. 44", 54", etc.
        public string Source { get; set; }//Joann
        public string Notes { get; set; }
        public List<string> Tags { get; set; }
        public int ItemsSold { get; set; }
        public virtual ICollection<Purchase> Purchases { get; set; }
    }
}

Это мой класс Migration "Add -igration FirstMigration"

namespace MyFabricStashApp.Migrations
{
    using System;
    using System.Data.Entity.Migrations;

    public partial class FirstMigration : DbMigration
    {
        public override void Up()
        {
            CreateTable(
                "dbo.Fabrics",
                c => new
                    {
                        FabricId = c.Int(nullable: false, identity: true),
                        MainCategoryId = c.Int(nullable: false),
                        SubCategory1Id = c.Int(nullable: false),
                        Name = c.String(),
                        ImagePath = c.String(),
                        Location = c.String(),
                        Type = c.String(),
                        Weight = c.String(),
                        Content = c.String(),
                        Design = c.String(),
                        Brand = c.String(),
                        Quantity = c.Double(nullable: false),
                        Width = c.Int(nullable: false),
                        Source = c.String(),
                        Notes = c.String(),
                        ItemsSold = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.FabricId)
                .ForeignKey("dbo.MainCategories", t => t.MainCategoryId, cascadeDelete: false)
                .ForeignKey("dbo.SubCategory1", t => t.SubCategory1Id, cascadeDelete: false)
                .Index(t => t.MainCategoryId)
                .Index(t => t.SubCategory1Id);

            CreateTable(
                "dbo.MainCategories",
                c => new
                    {
                        MainCategoryId = c.Int(nullable: false, identity: true),
                        Name = c.String(),
                    })
                .PrimaryKey(t => t.MainCategoryId);

            CreateTable(
                "dbo.SubCategory1",
                c => new
                    {
                        SubCategory1Id = c.Int(nullable: false, identity: true),
                        Name = c.String(),
                        MainCategoryId = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.SubCategory1Id)
                .ForeignKey("dbo.MainCategories", t => t.MainCategoryId, cascadeDelete: false)
                .Index(t => t.MainCategoryId);

            CreateTable(
                "dbo.Purchases",
                c => new
                    {
                        PurchaseId = c.Int(nullable: false, identity: true),
                        PurchaseDate = c.DateTime(nullable: false),
                        PurchaseQuantity = c.Int(nullable: false),
                        PurchasePrice = c.Double(nullable: false),
                        FabricId = c.Int(nullable: false),
                    })
                .PrimaryKey(t => t.PurchaseId)
                .ForeignKey("dbo.Fabrics", t => t.FabricId, cascadeDelete: false)
                .Index(t => t.FabricId);

        }

        public override void Down()
        {
            DropForeignKey("dbo.Fabrics", "SubCategory1Id", "dbo.SubCategory1");
            DropForeignKey("dbo.Purchases", "FabricId", "dbo.Fabrics");
            DropForeignKey("dbo.Fabrics", "MainCategoryId", "dbo.MainCategories");
            DropForeignKey("dbo.SubCategory1", "MainCategoryId", "dbo.MainCategories");
            DropIndex("dbo.Purchases", new[] { "FabricId" });
            DropIndex("dbo.SubCategory1", new[] { "MainCategoryId" });
            DropIndex("dbo.Fabrics", new[] { "SubCategory1Id" });
            DropIndex("dbo.Fabrics", new[] { "MainCategoryId" });
            DropTable("dbo.Purchases");
            DropTable("dbo.SubCategory1");
            DropTable("dbo.MainCategories");
            DropTable("dbo.Fabrics");
        }
    }
}

My FabricListViewModel.cs - я создал его, чтобы предоставить View доступ ко всемсвойства, которые мне нужны из всех моих классов.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MyFabricStashApp.Models
{
    public class FabricListViewModel
    {
        public int FabricId { get; set; } //Item Number

        public int MainCategoryId { get; set; }
        public string MainCategoryName { get; set; }

        public int SubCategory1Id { get; set; }
        public string SubCategory1Name { get; set; }

        public string Name { get; set; }
        public string ImagePath { get; set; }
        public string Location { get; set; }
        public string Type { get; set; } //Knit, Woven, Voile, Interfacing, Denim, Suiting, etc.
        public string Weight { get; set; }//Lightweight, Medium, Heavy
        public string Content { get; set; }//Cotton, Polyester, Nylon, etc.
        public string Design { get; set; }//Marvel Comics, Amy Butler, etc.
        public string Brand { get; set; } //Springs Creative Products, Free Spirit, Robert Kaufman, etc.
        public double Quantity { get; set; }//.25 yd, .50 yd, .75 yd, 1.0 yd, etc.
        public int Width { get; set; }// in inches, ie. 44", 54", etc.
        public string Source { get; set; }//Joann
        public string Notes { get; set; }
        public int ItemsSold { get; set; }
        public int PurchaseCount { get; set; }

    }
}

В моем контроллере FabricController вы можете видеть, что я включаю модели MainCategory и SubCategory1 в свой список, так что я могу получить доступ к их свойствам.Для краткости я включил действие Index и действие POST Create.

public class FabricController : Controller
    {
        private MyFabricStashDb db = new MyFabricStashDb();

        // GET: Fabric
        public ActionResult Index(string searchTerm = null)
        {
            var model = db.Fabrics.Include(f => f.MainCategory).Include(f => f.SubCategory1)
                .OrderByDescending(f => f.ItemsSold)
                .Where(f => searchTerm == null || f.Name.StartsWith(searchTerm))
                .Select(f => new FabricListViewModel
                {
                    FabricId = f.FabricId,
                    Name = f.Name,
                    MainCategoryId = f.MainCategoryId,
                    MainCategoryName = f.MainCategory.Name,
                    SubCategory1Id = f.SubCategory1Id,
                    SubCategory1Name = f.SubCategory1.Name,
                    ImagePath = f.ImagePath,
                    Location = f.Location,
                    Type = f.Type,
                    Weight = f.Weight,
                    Content = f.Content,
                    Design = f.Design,
                    Brand = f.Brand,
                    Quantity = f.Quantity,
                    Width = f.Width,
                    Source = f.Source,
                    Notes = f.Notes,
                    ItemsSold = f.ItemsSold,
                    PurchaseCount = f.Purchases.Count()
                });
            return View(model);
        }
// POST: Fabric/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see https://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "FabricId,MainCategory,SubCategory1,SubCategory2,Name,ImagePath,Location,Type,Weight,Content,Design,Brand,Quantity,Width,Source,Notes,ItemsSold")] Fabric fabric, HttpPostedFileBase file)
        {
            if (ModelState.IsValid)
            {
                var filename = Path.GetFileName(file.FileName);
                string fabricId = fabric.FabricId.ToString();
                string myfile = fabricId + "_" + filename;
                var path = Path.Combine(Server.MapPath("~/images"), myfile);
                fabric.ImagePath = myfile;
                file.SaveAs(path);
                db.Fabrics.Add(fabric);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(fabric);
        }

Нужно ли связывать свойства классов MainCategory и SubCategory1 в моем методе POST Create?Может быть, поэтому оператор INSERT не выполняется?Сбой на "db.SaveChanges ();"строка в методе действия POST Create.

Когда я закомментирую свойство lines public virtual MainCategory MainCategory {get; set;} в классе Fabric, оно работает, и я могу создать новый Item, однако я не могу ВКЛЮЧИТЬ эти классы в мой FabricController, потому что свойства не существуютв классе Fabric, поэтому я не могу получить доступ к их свойствам.

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Я выкладываю разрешение моей проблемы здесь.На него в комментариях ответили @juharr и @ user1011627 выше, но я хотел опубликовать решение на случай, если кто-то столкнется с той же проблемой.

Я просто добавил свойства "MainCategoryId" и "SubCategory1Id" в свой оператор BIND вPOST Создать метод действия.См. Ниже в FabricController:

// POST: Fabric/Create
        // To protect from overposting attacks, please enable the specific properties you want to bind to, for 
        // more details see https://go.microsoft.com/fwlink/?LinkId=317598.
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create([Bind(Include = "FabricId,MainCategory,MainCategoryId, SubCategory1Id,SubCategory1,SubCategory2,Name,ImagePath,Location,Type,Weight,Content,Design,Brand,Quantity,Width,Source,Notes,ItemsSold")] Fabric fabric, HttpPostedFileBase file)
        {
            if (ModelState.IsValid)
            {
                var filename = Path.GetFileName(file.FileName);
                string fabricId = fabric.FabricId.ToString();
                string myfile = fabricId + "_" + filename;
                var path = Path.Combine(Server.MapPath("~/images"), myfile);
                fabric.ImagePath = myfile;
                file.SaveAs(path);
                db.Fabrics.Add(fabric);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(fabric);
        }

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

0 голосов
/ 11 июня 2018

Loooong вопрос, вот способ упростить ваши данные.Каждая подкатегория имеет уникальный идентификатор.Чтобы сделать ссылку на основную категорию, вы можете перейти в подкатегорию, к которой относится ткань.Это дает нам

public class Fabric
    {
        public int FabricId { get; set; } //Item Number

        // public int MainCategoryId { get; set; }
        // public virtual MainCategory MainCategory { get; set; }

        public int SubCategory1Id { get; set; }
        public virtual SubCategory1 SubCategory1 { get; set; }
        public string Name { get; set; }
        public string ImagePath { get; set; }
        public string Location { get; set; }
        public string Type { get; set; } //Knit, Woven, Voile, Interfacing, Denim, Suiting, etc.
        public string Weight { get; set; }//Lightweight, Medium, Heavy
        public string Content { get; set; }//Cotton, Polyester, Nylon, etc.
        public string Design { get; set; }//Marvel Comics, Amy Butler, etc.
        public string Brand { get; set; } //Springs Creative Products, Free Spirit, Robert Kaufman, etc.
        public double Quantity { get; set; }//.25 yd, .50 yd, .75 yd, 1.0 yd, etc.
        public int Width { get; set; }// in inches, ie. 44", 54", etc.
        public string Source { get; set; }//Joann
        public string Notes { get; set; }
        public List<string> Tags { get; set; }
        public int ItemsSold { get; set; }
        public virtual ICollection<Purchase> Purchases { get; set; }
    }

И пока вы извлекаете Fabric с помощью

db.Fabrics.Include("SubCategory1").Include("SubCategory1.MainCategory").FirstOrDefault(p => p.FabricId == <something>);

Вы можете ссылаться на Fabric.SubCategory1.MainCategory.Name

Используя MainCategory / SubCategory1 дляЗаполните выпадающие списки и убедитесь, что при создании вы добавили ключ SubCategory1 в вашу запись Fabric.Должно упростить вашу жизнь.Ваши выпадающие списки будут привязаны к временному полю для MainCategory и вашей модели списка для SubCategory1.SubCategoryId.Для отображения вы должны заполнить временное поле из поля Fabric.SubCategory1.MainCategory.MainCategoryId.YMMV.

...