【问题标题】:Issue with Entity Framework/db relations实体框架/数据库关系问题
【发布时间】:2011-11-16 05:23:59
【问题描述】:

我有一篇课文:

    public class Article
{
    public int Id { get; set; }
    public string Text { get; set; }
    public Title Title { get; set; }

}

和标题:

    public class Title
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int MaxChar { get; set; }   
}

在您编写Article 之前,您必须从列表中选择您的Title,这样您就可以确定Article.Text 的StringLength。意思是,这篇文章只能有一定数量的字符,这取决于作者的“标题”。例子:Title.Name“Title1”只能写一篇1000字的文章(MaxChar),Title.Name“Title2”可以写一篇3000字的文章。所以。这意味着Article.Text 的字符串长度必须来自Title.MaxChar

Title 实体是存储在数据库中的前缀数据。

这是我迄今为止所做的: 数据库中的标题列在一个视图中,并带有一个链接以使用“标题”查询字符串创建 ArticleController 的操作:

    @Models.Title

@foreach (var item in Model) {
         @Html.ActionLink(item.Name, "Create", "Article", new { title = item.Id}, new FormMethod())

        }

您填写表格,然后发布。 HttpPost 创建操作:

    [HttpPost]
    public ActionResult Create(Article article)
    {
        if (article.Text.Length > article.Title.MaxChar)
        {
            ModelState.AddModelError("Text",
                                     string.Format("The text must be less than {0} chars bla bla", article.Title.MaxChar));
        }
        if (ModelState.IsValid)
            {
                db.Article.Add(article);
                db.SaveChanges();
                return RedirectToAction("Index");
            }


        return View(hb);
    }

问题来了。控制器还添加了一个新的Title 实体。因此,下次我导航到必须选择标题的视图时,会出现我用来写文章的最后一个实体的副本。

我应该以一种全新的方式来做这件事,还是有一个小的调整。我能想到的唯一另一件事就是将MaxChar 作为查询字符串发送,并且模型之间根本没有关系。只是看起来有点傻/webforms kindda。

干杯

更新#1: 也许我做错了? 获取创建操作

        public ActionResult Create(int title)
    {
        var model = new Article
        {
            Title = db.Title.Find(title)
        };
        return View(model);
    } 

或者也许它在模型中?比如,我必须设置外键吗?比如:

        [ForeignKey("Title")]
    public int MaxChar { get; set; }
    public virtual Title Title { get; set; }

但我很确定我读到了一些不需要的地方,EF 会处理这个问题。

【问题讨论】:

  • 好像Title的Id属性不是主键(或唯一)?
  • @counsellorben 代码优先是
  • 请发布Create 视图。您是否将 Title.Id 作为隐藏字段包含在您的视图中。如果不是,则不会将 Title.Id 发回您的 Create POST 操作,这将导致添加新的 Title 记录。
  • @counsellorben 当然,我可以看到。但我必须包含 Title.MaxChar 才能控制 Article.Text 的长度。但是,正如你所说,一旦我创建了一篇文章,它就会创建一条 Title.Id 和 Title.Name = null 的重复记录。
  • @counsellorben 我已经用一些代码更新了这个问题。我怀疑这就是原因。

标签: asp.net-mvc-3 entity-framework-4.1 database-relations


【解决方案1】:

您需要区分 MVC 模型和实体模型。您的 MVC 文章模型应如下所示(请记住,关于模型的内容存在一些宗教争论):

public class Article
{
    public int Id { get; set; }
    public string Text { get; set; }
    public int TitleID { get; set; }
    public IEnumerable<Title> AvailableTitles {get;set;}
}

在您看来,您可以根据可用标题创建一个下拉列表,并将其绑定到 TitleID 属性。可用标题列表将填充到无参数控制器方法(以及模型绑定方法)中。

当您的模型绑定方法返回 TitleID 时,根据 ID 从实体框架实例化 Title 对象。使用该 Title 对象创建您的 Entities Article 对象,并保存您的更改。这应该能让你到达你想去的地方。

【讨论】:

  • 优雅的解决方案。将在未来的项目中这样做。但是我不喜欢 Slaumas 解决方案,因为我只需要添加一行就可以了 :)
【解决方案2】:

最简单的方法可能是将标题附加到您的 Create 操作中的上下文中:

// ...
if (ModelState.IsValid)
{
    db.Titles.Attach(article.Title);
    db.Article.Add(article);
    db.SaveChanges();
    return RedirectToAction("Index");
}
// ...

Attach 告诉 EF article.Title 已经存在于数据库中,从而避免在将文章添加到上下文时插入新的 Title

【讨论】:

    猜你喜欢
    • 2017-05-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多