【问题标题】:CRUD for joinned view with LINQ to SQL class C# MVC用于使用 LINQ to SQL 类 C# MVC 连接视图的 CRUD
【发布时间】:2015-11-10 16:49:15
【问题描述】:

这是我的问题的一些背景:

  1. 我的应用程序中有一个强类型视图,用于显示列表。
  2. 一旦我想要显示的信息来自不同的表,我必须在我的 LINQ 查询中进行一些连接,因此我必须创建一个自定义模型。
  3. 现在我想使用列表行的 ID 来实现 CRUD 操作。

模型

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Globalization;
using System.Web.Security;

namespace LMWEB_MVC.Models
{
    public class LeaseViewModel
    {
        [Key] public int Lease_Detail_ID { get; set; }
        public string Lease_ID { get; set; }
        public string XRef_Lease_ID { get; set; }
        public string Vendor_Name { get; set; }
        public string Description { get; set; }
        public string County { get; set; }
        public decimal Amount { get; set; }
        public DateTime Payment_Due_Date { get; set; }
        public short Authorized { get; set; }
        public string Line_Type { get; set; }
    }

    public class LeasesContext : DbContext
    {
        public LeasesContext()
            : base("LMWEBConnectionString1")
        {
            Database.SetInitializer<Models.LeasesContext>(null);
        }

        public DbSet<LeaseViewModel> LeaseViewModels { get; set; }
    }

}

观点

@model IEnumerable<LMWEB_MVC.Models.LeaseViewModel>

@{
    ViewBag.Title = "Leases";
}

<link href="../Styles/style.css" rel="stylesheet" type="text/css">

<h2>Leases</h2>
<div>

</div>
<div>
    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
</div>
<div style="scrollbar-base-color: #eeeeee; background: white; position: relative; border-right: black 1px solid;
border-top: black 1px solid; overflow-y: scroll; border-left: black 1px solid; border-bottom: black 1px solid;
height: 650px; width:100%; border-spacing: 10px 10px">
    <table>
        <tr>
            <th style="width: 65px;" class="head">
                @Html.DisplayNameFor(model => model.Lease_ID)
            </th>
            <th style="width: 75px;" class="head">
                @Html.DisplayNameFor(model => model.XRef_Lease_ID)
            </th>
            <th style="width: 85px;" class="head">
                @Html.DisplayNameFor(model => model.Vendor_Name)
            </th>
            <th style="width: 185px;" class="head">
                @Html.DisplayNameFor(model => model.Description)
            </th>
            <th style="width: 85px;" class="head">
                @Html.DisplayNameFor(model => model.County)
            </th>
            <th style="width: 85px;" class="head">
                @Html.DisplayNameFor(model => model.Amount)
            </th>
            <th style="width: 60px;" class="head">
                @Html.DisplayNameFor(model => model.Payment_Due_Date)
            </th>
            @*<th style="width: 70px;" class="head">
                    @Html.DisplayNameFor(model => model.Authorized)
                </th>*@
            <th style="width: 70px;" class="head">
                @Html.DisplayNameFor(model => model.Line_Type)
            </th>
            <th style="width: 20px;" class="head"></th>
        </tr>

        @foreach (var item in Model)
        {
            <tr>
                <td style="width: 65px; word-wrap: break-word;" class="leasegrid">
                    @Html.DisplayFor(modelItem => item.Lease_ID)
                </td>
                <td style="width: 75px; word-wrap: break-word;" class="leasegrid">
                    @Html.DisplayFor(modelItem => item.XRef_Lease_ID)
                </td>
                <td style="width: 85px; word-wrap: break-word;" class="leasegrid">
                    @Html.DisplayFor(modelItem => item.Vendor_Name)
                </td>
                <td style="width: 185px; word-wrap: break-word;" class="leasegrid">
                    @Html.DisplayFor(modelItem => item.Description)
                </td>
                <td style="width: 85px; word-wrap: break-word;" class="leasegrid">
                    @Html.DisplayFor(modelItem => item.County)
                </td>
                <td style="width: 85px; word-wrap: break-word;" class="leasegrid">
                    @Html.DisplayFor(modelItem => item.Amount)
                </td>
                <td style="width: 60px; word-wrap: break-word;" class="leasegrid">
                    @Html.DisplayFor(modelItem => item.Payment_Due_Date)
                </td>
                @*<td class="leasegrid">
                           @Html.DisplayFor(modelItem => item.Authorized)
                    </td>*@
                <td style="width: 70px;" class="leasegrid">
                    @Html.DisplayFor(modelItem => item.Line_Type)
                </td>
                <td style="width: 140px;" class="leasegrid">
                    @Html.ActionLink("Edit", "Edit", new { item.Lease_Detail_ID }, null) |
                    @Html.ActionLink("Details", "Details", new { item.Lease_Detail_ID }, null) |
                    @Html.ActionLink("Delete", "Delete", new { item.Lease_Detail_ID }, null)
                </td>
            </tr>
        }

    </table>
</div>

控制器

using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using LMWEB_MVC.Models;

namespace LMWEB_MVC.Controllers
{
    public class LeasesController : Controller
    {

        public ActionResult Leases()
        {
            LMWEBLINQDataContext leases = new LMWEBLINQDataContext();
            var leaseList = (from l in leases.tblfLeaseDetails
                             join v in leases.tblvVendors on l.Vendor_ID equals v.Vendor_ID
                             join c in leases.tblvCounties on l.County_ID equals c.County_ID
                             join a in leases.tblfAuthorizations on l.Lease_Detail_ID equals a.Lease_Detail_ID
                             join t in leases.tblvLineTypes on l.Line_Type_ID equals t.Line_Type_ID
                             select new
                             {
                                 l.Lease_Detail_ID,
                                 l.Lease_ID,
                                 l.XRef_Lease_ID,
                                 v.Vendor_Name,
                                 l.Description,
                                 c.County,
                                 l.Amount,
                                 l.Payment_Due_Date,
                                 a.Authorized,
                                 t.Line_Type
                             }).Distinct().ToList().ToNonAnonymousList(new List<LeaseViewModel>()).Take(10);

            ViewBag.Message = "Your app description page.";
            return View(leaseList);
        }

        private LeasesContext db = new LeasesContext();

        //
        // GET: /Leases/

        public ActionResult Index()
        {
            return View(db.LeaseViewModels.ToList());
        }

        //
        // GET: /Leases/Details/5

        public ActionResult Details(int Lease_Detail_ID = 0)
        {
            LeaseViewModel leaseviewmodel = db.LeaseViewModels.Find(Lease_Detail_ID);
            if (leaseviewmodel == null)
            {
                return HttpNotFound();
            }
            return View(leaseviewmodel);
        }

        //
        // GET: /Leases/Create

        public ActionResult Create()
        {
            return View();
        }

        //
        // POST: /Leases/Create

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create(LeaseViewModel leaseviewmodel)
        {
            if (ModelState.IsValid)
            {
                db.LeaseViewModels.Add(leaseviewmodel);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            return View(leaseviewmodel);
        }

        //
        // GET: /Leases/Edit/5

        public ActionResult Edit(int Lease_Detail_ID = 0)
        {
            LeaseViewModel leaseviewmodel = db.LeaseViewModels.Find(Lease_Detail_ID);
            if (leaseviewmodel == null)
            {
                return HttpNotFound();
            }
            return View(leaseviewmodel);
        }

        //
        // POST: /Leases/Edit/5

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Edit(LeaseViewModel leaseviewmodel)
        {
            if (ModelState.IsValid)
            {
                db.Entry(leaseviewmodel).State = EntityState.Modified;
                db.SaveChanges();
                return RedirectToAction("Index");
            }
            return View(leaseviewmodel);
        }

        //
        // GET: /Leases/Delete/5

        public ActionResult Delete(int Lease_Detail_ID = 0)
        {
            LeaseViewModel leaseviewmodel = db.LeaseViewModels.Find(Lease_Detail_ID);
            if (leaseviewmodel == null)
            {
                return HttpNotFound();
            }
            return View(leaseviewmodel);
        }

        //
        // POST: /Leases/Delete/5

        [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public ActionResult DeleteConfirmed(int Lease_Detail_ID)
        {
            LeaseViewModel leaseviewmodel = db.LeaseViewModels.Find(Lease_Detail_ID);
            db.LeaseViewModels.Remove(leaseviewmodel);
            db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}

我收到的错误

System.Data.Entity.dll 中出现“System.Data.EntityCommandExecutionException”类型的异常,但未在用户代码中处理

附加信息:执行命令定义时出错。有关详细信息,请参阅内部异常。

内部异常

{"无效的对象名称'dbo.LeaseViewModels'。"}

最后(感谢您到达这里)我的问题:

我了解我的所有 CRUD 操作都没有完成,因为我的数据库中没有 dbo.LeaseViewModels。 LeaseViewModels 只是我创建的一个模型,用于存储我的连接查询。所以这是我的疑问:如何从这个自定义视图开始在我的数据库中实现 CRUD 操作?可能吗?如果不是,如果不使用自定义模型,我如何创建包含来自不同表的信息的视图?

注意:我没有 DBO 访问我的数据库的权限。我只能读取和执行程序。

【问题讨论】:

  • 首先创建表。要么运行脚本来创建它们,要么运行实体框架迁移。该异常是实体框架异常,而不是 LINQ-to-SQL。除此之外,请查看 Entity Framework 教程或 Microsoft Virtual Academy 中的课程。
  • 感谢您的回答,Panagiotis!我刚刚添加了一条注释,通知我没有对我的数据库的完全访问权限。这让我意识到我的控制器应该尝试运行我的程序,对吗?我尝试使用实体框架,但收到 NuGet 错误,最终使用 LINQ-to-SQL。我创建实体框架模型时是否有任何剩余代码?
  • 如果遇到 NuGet 错误,请修复 nuget 错误。不要丢弃主要的 .NET ORM,因为您认为它已损坏。同样,我建议您参加教程或课程。这太基础了,如果你没有意识到你完全在使用 EF,你就无法创建应用程序,而不仅仅是一些剩余代码
  • 不幸的是,无法选择参加课程,这就是我在这里寻求帮助的原因。但我肯定会寻找一些教程。感谢您的建议。

标签: c# asp.net-mvc linq join crud


【解决方案1】:

问题出在您的 DbContext 中。 DbContext 类应该将数据库表映射到应用程序的域类。

从 DbContext 中删除 LeaseViewModel 并添加数据库的表(例如供应商和国家/地区)。然后,您可以使用 linq 表达式来连接表并为您的视图返回一个 LeaseViewModel 对象。

希望对你有帮助。

更新

我正在添加一些有关 EF 映射的链接,可能会对您有所帮助:

【讨论】:

  • 谢谢你的回答,亚历山大!我使用类似 public DbSet tblvVendors { get; 之类的代码在我的 DbContext 中创建了所有表。放; } 为每个表,并按照您的建议删除了 LeaseViewModel。一旦 db.LeaseViewModels.Find(Lease_Detail_ID); 无法再访问,它就会导致我的控制器在所有 CRUD 方法中出现问题。我考虑过再次创建控制器,这次使用新的/固定的上下文作为参考,但这导致了 dataModel 错误,因为我的主键没有在 db 中正确设置。我会修复它并让你知道它是否有效。感谢您的帮助!
  • 检查域类的映射,它们应该与数据库模式匹配,否则实体框架将抛出​​异常。我用一些关于 EF 映射的链接更新了我的答案。
【解决方案2】:

您创建 DbContext 类的方式是寻找一个名为 LeaseViewModel 的表。如果您无法创建该表,则需要更改您的 DbContext 以实际将 DbSets 保存为 tblfLeaseDetails、tblvVendors、tblvCounties 等。然后在控制器中(或者在某些 DAL 模块中更好),您可以使用类似于您的连接来创建您的视图模型,然后在控制器中使用该视图模型。

【讨论】:

  • 谢谢你的回答,苛刻! 1st: 我在我的 LINQ.designer.cs 文件中设置了所有这些表(它们都是在我创建 LINQ-to-SQL 类时自动创建的),但是当我尝试创建 Strongly-带有我的 LINQ 上下文的类型化控制器它说上下文是未预料到的,这就是为什么我在模型中使用上下文来创建控制器的原因。我应该只从 LINQ 设计器文件中复制模型吗?这些定义是否相同? 第二个:我应该在控制器中声明我的自定义模型?
猜你喜欢
  • 2011-07-18
  • 1970-01-01
  • 2015-06-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多