简体   繁体   English

ASP.NET MVC的实体框架

[英]Entity Framework with ASP.NET MVC

How can I use strongly-typed Controllers with EntityObjects? 如何在EntityObjects中使用强类型控制器?

My failures... 我的失败......

First I tried this: 首先我尝试了这个:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    db.SaveChanges();
    return RedirectToAction("Index");
}

This failed to actually save any changes to the database. 这实际上无法保存对数据库的任何更改。 So, I tried to attach the model to my ObjectContext: 所以,我试图将模型附加到我的ObjectContext:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    db.Attach(Model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

This failed because "an object with a null EntityKey value cannot be attached to an object context." 这失败了,因为“具有null EntityKey值的对象无法附加到对象上下文”。 So, I tried to assign the EntityKey: 所以,我试图分配EntityKey:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    Model.EntityKey = (from Department d in db.Department
                       where d.Id == id
                       select d).FirstOrDefault().EntityKey;
    db.Attach(Model);
    db.SaveChanges();
    return RedirectToAction("Index");
}

This failed because "an object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key." 这失败是因为“ObjectStateManager中已经存在具有相同键的对象.ObjectStateManager无法跟踪具有相同键的多个对象。”

How is this supposed to work? 这应该怎么样?

The thing is, what you have as your input is not a complete model object with changed properites - it is just a "start" of new one, with all the properties that you want to overwrite on an already existing entity. 问题是,你输入的内容并不是一个完整的模型对象,它具有更改的属性 - 它只是一个新的“开始”,具有你想要覆盖已经存在的实体的所有属性。 You don't post any of the ID properties, 您没有发布任何ID属性,

This looks a little verbose, but it's the best I've found, so it is how I do it in my projects (ajusted to your class names, with whatever was missing made up...): 这看起来有点冗长,但它是我发现的最好的,所以这就是我在我的项目中做到的方式(调整到你的班级名称,不管失去了什么......):

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model)
{
    var dbDepartment = (from Department d in db.Department
                        where d.Id == id
                        select d).FirstOrDefault() as Department

    dbDepartment.Name = Model.Name;
    dbDepartment.Color = Model.Color;
    // etc, assigning values manually...

    try
    {
        db.SaveChanges();
    }
    catch (Exception ex)
    {
        // oops...
    }
    return RedirectToAction("Index");
}

Try db.AttachTo() instead of db.Attach() 尝试db.AttachTo()而不是db.Attach()

As described here 如上所述这里

"Call AttachTo on ObjectContext to attach the object to a specific entity set in the object context. Also do this if the object has a null (Nothing in Visual Basic) EntityKey value." “在ObjectContext上调用AttachTo以将对象附加到对象上下文中的特定实体集。如果对象具有null(在Visual Basic中为Nothing)EntityKey值,也执行此操作。”

Edit: actually, you may need to call ApplyPropertyChanges() in this case. 编辑:实际上,在这种情况下,您可能需要调用ApplyPropertyChanges()。

Edit 2: You can build an entity key for your object with code like the following: 编辑2:您可以使用以下代码为对象构建实体密钥:

public EntityKey GetEntityKey(string entitySetName, object keyValue)
{
  IEnumerable<KeyValuePair<string, object>> entityKeyValues =
    new[]
    {
      new KeyValuePair<string, object>("Id", keyValue)
    };

  var key = new EntityKey(string.Concat("YOUR_OBJECT_CONTEXT_NAME.", entitySetName), entityKeyValues);
  return key;
}

And then you'd call this with something like this for entity keys based on a single database column called 'Id': 然后你会根据一个名为'Id'的单个数据库列为实体键调用这个类似的东西:

var entityKey = GetEntityKey("Customer", 23); var entityKey = GetEntityKey(“Customer”,23);

I use a similar method in my own EF code except with a Generic type argument to avoid having to use a string for the entity class name. 我在自己的EF代码中使用了类似的方法,除了使用Generic类型参数以避免必须使用字符串作为实体类名。

How about this 这个怎么样

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(int id, Department dept)
{
    Department tmp = new Department()
    {
        Id = dept.Id
    };
    try
    {
        db.Departments.Attach(dept, tmp);
        db.Save();
    }
}

Maybe the tmp-part can be exchanged for a call to UpdateModel after the Attach part, but I'm not sure. 也许tmp-part可以在Attach部分之后交换对UpdateModel的调用,但我不确定。

Edit: Just looked up the documentation on Attach(Entity e, Entity original) and it does indeed replace original with e (or update original accordingly or w/e). 编辑:只需查看Attach(Entity e,Entity original)上的文档,它确实用e替换原文(或相应更新原文或w / e)。

I don not recommend to use a POCO into you MVC application. 我不建议在您的MVC应用程序中使用POCO。 You should use a DTO or a model. 您应该使用DTO或模型。

Maybe you should retrieve an object by id before and then replace the values you supplied by arguments to edit method and then save changes. 也许您应该先通过id检索一个对象,然后将参数提供的值替换为edit方法,然后保存更改。 You get an error because you didn't deattach the model in the first place. 您收到错误是因为您没有首先取消模型。

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Guid id, Department Model) {
var entity=from m in db.Models where m.Id == Model.id select m;
Model entityAttached=entity.FirstOrDefault();
//replace all the new values in you object
db.SaveChanges();
}

or deattach object when you get it by id and attach it back when you want to save the new values in edit method. 当你想要在编辑方法中保存新值时,或者当你通过id获取它时将其附加到deattach对象并将其附加回来。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM