Свойство внешнего ключа не будет установлено правильно - PullRequest
0 голосов
/ 28 февраля 2020

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

Это мои классы моделей.

[Table("Store")]
    public class Store
    {
        [Key]
        public int StoreId { get; set; }

        public string Name { get; set; }

        public string Address { get; set; }
    }
    [Table("Purchase")]
    public class Purchase
    {
        [Key]
        public int Id { get; set; }

        public int StoreId { get; set; }

        [ForeignKey("StoreId")]
        public Store Store { get; set; }
    }

    public class PurchaseDBContext : DbContext
    {
        public DbSet<Purchase> Purchases { get; set; }
        public DbSet<Store> Stores { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {

        }
    }
public class PurchaseCreateHelper
    {
        public Purchase Purchase { get; set; }
        public List<Store> Stores { get; set; }
    }
}

Моя релевантная часть View для этого вопроса:

<div class="form-group">
        @Html.LabelFor(model => model.Purchase.StoreId, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(model => model.Purchase.StoreId, new SelectList(Model.Stores.Select( x => new { StoreId = x.StoreId, DisplayName = x.Name.ToString() + " - " + x.Address.ToString()}), "StoreId", "DisplayName"), new { @class = "form-control" })
            @Html.ValidationMessageFor(model => model.Purchase.StoreId, "", new { @class = "text-danger" })
        </div>
    </div>

И соответствующая часть моего контроллера:

        // GET: Purchases/Create
        public ActionResult Create()
        {
            var purchaseHelper = new PurchaseCreateHelper()
            {
                Stores = db.Stores.ToList(),
                Purchase = new Purchase()
            };

            return View(purchaseHelper);
        }

        // POST: Purchases/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(Purchase purchase)
        {
            if (ModelState.IsValid)
            {
                db.Purchases.Add(purchase);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(purchase);
        }

Когда мой код приходит к db.Purchases.Add (покупка), свойство Store объекта покупки устанавливается в нуль , Однако StoreId, похоже, в порядке. Я не понимаю, почему объект Store не изменяется со свойством StoreId, поскольку я аннотировал его [ForeignKey ("StoreId")]. Где я испортил соединение между StoreId и Store?

UPDATE # 2

        // GET: Purchases
        public ActionResult Index()
        {
            return View(db.Purchases.ToList());
        }
@model IEnumerable<BookKeeper.Models.Purchase>

@{
    ViewBag.Title = "Index";
}

<h2>Index</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>

<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.Store.Name)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Type)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Price)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.Date)
        </th>
        <th></th>
    </tr>

@foreach (var item in Model) {
<tr>
    <td>
        @Html.DisplayFor(modelItem => (item.Store.Name))
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Type)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Price)
    </td>
    <td>
        @Html.DisplayFor(modelItem => item.Date)
    </td>
    <td>
        @Html.ActionLink("Edit", "Edit", new { id = item.Id }) |
        @Html.ActionLink("Details", "Details", new { id = item.Id }) |
        @Html.ActionLink("Delete", "Delete", new { id = item.Id })
    </td>
</tr>
}

</table>

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

1 Ответ

1 голос
/ 28 февраля 2020

Я предполагаю, что вы не видите никакого значения для покупки. Это связано с тем, что связыватель модели привязывает только StoreId (когда запрос отправляется из браузера на веб-сервер), который вы указали в

@Html.DropDownListFor(model => model.Purchase.StoreId, new SelectList(Model.Stores.Select( x => new { StoreId = x.StoreId, DisplayName = x.Name.ToString() + " - " + x.Address.ToString()}), "StoreId", "DisplayName"), new { @class = "form-control" })

Заполнение покупки. Магазин принадлежит EF. EF загрузит это хранилище, когда вы выполните

dbContext.Purchases.Include(x => x.Store).FirstOrDefault(x => x.ID == 1234);

ОБНОВЛЕНИЕ:

Если вы хотите, чтобы объект хранилища в действии POST

    // POST: Purchases/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(Purchase purchase)
    {
        if (ModelState.IsValid)
        {
            db.Purchases.Add(purchase);
            db.SaveChanges();
            purchase = dbContext.Purchases.Include(x => x.Store).FirstOrDefault(x => x.ID == purchase.ID); // Not sure why you need Store information at this step.
            return RedirectToAction("Index");
        }

        return View(purchase);
    }
...