ASP.NET MVC与EF 4.1导航性能 [英] ASP.NET MVC with EF 4.1 Navigation properties

查看:212
本文介绍了ASP.NET MVC与EF 4.1导航性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在天EF学习理解(有点..)它是如何工作的,我终于意识到,我可能有一个很大的问题。

After days studying EF to understand (kinda..) how it works, I finally realized that I might have a big problem.

想象一下,我有两个实体:派斯 UF 。它们之间的关系是派斯(0..1)...(*)UF 。截图: http://i.imgur.com/rSOFU.jpg

Imagine that I have two entities: Pais and UF. The relationship between them is Pais (0..1) ... (*) UF. A screenshot: http://i.imgur.com/rSOFU.jpg.

说,考虑到我有一个名为控制器 UFController ,它有编辑动作创建,这是就好了。我的意见是使用输入 EditorFor 助手(或类似的),所以当我提交表单,控制器将获得 UF 充满了所有的数据(自动)与参考物体的的几乎是空的派斯。我的看法code(的一部分):

Said that, consider that I have a controller called UFController and it has actions for Edit and Create, which are just fine. My views are using the EditorFor helper (or similar ones) for inputs, so when I submit the form the controller will receive a UF object filled with all the data (automatically) with a reference to an almost-empty Pais. My view code (part of it):

@* UF attributes *@
@Html.EditorFor(m => m.Sigla)
@Html.EditorFor(m => m.Descricao)
@Html.EditorFor(m => m.CodigoIBGE)
@Html.EditorFor(m => m.CodigoGIA)
@* Pais primary key ("ID") *@
@Html.EditorFor(m => m.Pais.Codigo) // Pais id

控制器修改操作code:

[HttpPost]
public ActionResult Edit(UF uf)
{
    try
    {
        if (ModelState.IsValid)
        {
            db.UFs.Attach(uf);
            db.ObjectStateManager.ChangeObjectState(uf, EntityState.Modified);
            db.SaveChanges();

            return this.ClosePage(); // An extension. Just ignore it.
        }
    }
    catch (Exception e)
    {
        this.ModelState.AddModelError("Model", e.Message.ToString());
    }

    return View(uf);
}

当我提交表单,这是什么动作接收为 UF

When I submit the form, this is what the action receives as uf:

{TOTALWeb.UF}
    base {System.Data.Objects.DataClasses.EntityObject}: {TOTALWeb.UF}
    (...)
    CodigoGIA: 0
    CodigoIBGE: 0
    Descricao: "Foobar 2001"
    ID: 936
    Pais: {TOTALWeb.Pais}
    PaisReference: {System.Data.Objects.DataClasses.EntityReference<TOTALWeb.Pais>}

uf.Pais

{TOTALWeb.Pais}
    base {System.Data.Objects.DataClasses.EntityObject}: {TOTALWeb.Pais}
    Codigo: 0
    CodigoBACEN: null
    CodigoGIA: null
    CodigoIBGE: null
    Descricao: null
    UF: {System.Data.Objects.DataClasses.EntityCollection<TOTALWeb.UF>}

原来的信息(一个数据库)为 uf.Pais.Codigo == 716 。所以,现在我收到更新的信息。在该数据库中的控制器不upading的FK问题

The original information (the one on the database) is uf.Pais.Codigo == 716. So, right now I'm receiving the updated information. The problem on that the controller is not upading the FK in the database.

我不希望从 uf.Pais 设置为EntityState 修改因为实体本身WASN T改为(我没有改变从条目中的信息),但是的关系的了。

I don't want to set the EntityState from uf.Pais to Modified because the entity itself wasn't changed (I didn't changed the information from that entry), but the relationship was.

在换句话说,我想要做的是改变FK的值,指向 uf.Pais 的另一个实例派斯。据我所知,这是不可能的关系状态更改为修改(抛出一个异常),所以我在寻找替代解决方案。

In other words, what I'm trying to do is change the value of the FK, pointing the uf.Pais to another instance of Pais. Afaik, it's impossible to change the relationship state to Modified (throw an exception), so I'm looking for alternative solutions.

我读了一堆,我在谷歌找到有关这一类问题的话题,但我仍然没有找到一个简单而优雅的解决方案。在最后的我读到这里计算器:

I've read a bunch of topics I've found on Google about this kind of problem, but I still didn't find a simple and elegant solution. The last ones I read here on stackoverflow:

  • How to work with navigation properties (/foreign keys) in ASP.NET MVC 3 and EF 4.1 code first
  • Strongly-Typed ASP.NET MVC with ADO.NET Entity Framework
  • Getting Error 3007 when I add my Entity Model

我问一个问题,前几天有关类似问题(<一个href=\"http://stackoverflow.com/questions/6956026/entity-framework-4-1-default-entitystate-for-a-fk\">Entity框架4.1 - 为FK默认EntityState )。我不明白EF是如何工作的那段时间,所以现在一堆东西看起来很清楚,我(这就是为什么我在打开一个新的问题)。

I asked a question a few days ago about a similar problem ( Entity Framework 4.1 - default EntityState for a FK? ). I didn't understand how EF works that time, so now a bunch of things look clear to me (that's why I'm opening a new question).

对于创建我一直在测试这个解决方案(在我的其他问题提出了拉吉斯拉夫)的行动,但它会产生一个额外的选择(可以是最终缓慢美国):

For the Create action I've been testing this solution (proposed by Ladislav on my other question), but it generates an additional select (which can be eventually slow for us):

// Here UF.Pais is null
db.UFs.AddObject(uf);
// Create dummy Pais
var pais = new Pais { Id = "Codigo" };
// Make context aware of Pais
db.Pais.Attach(pais); // <- Executing a SELECT on the database, which -can- be slow.
// Now make the relation
uf.Pais = pais;
db.SaveChanges();

我可以复制本作的修改(我猜的),但我不希望更多的选择。

I can replicate this for the Edit (I guess), but I don't want that additional SELECT.

所以,在简历:我试图使用导航属性将数据发送到控制器,并使用快速简便的方法(不搞乱太多与实体直接在数据库中保存他们 - 这些的很简单,但我们有很多FKS的庞大和非常复杂的!)。我的问题是:有不涉及在数据库中执行另一个查询(简单的)解决方案

So, in resume: I'm trying to use navigation properties to send data to the controller and save them directly in the database using a fast and easy way (without messing too much with the entity - these ones are simple, but we have huge and very complex ones with a lot of FKs!). My question is: there's a solution that doesn't involve executing another query in the database (a simple one)?

谢谢,

里卡多

PS:对不起任何英语的错误和混乱的任何

PS: sorry for any english mistakes and any confusions.

更新1 :使用BennyM的解决方案(种..)

Update 1: using BennyM's solution (kind of..)

我测试了以下code,但它不工作。它抛出一个异常:具有相同的键已经存在于ObjectStateManager的ObjectStateManager不能用相同的密钥跟踪多个对象的对象。大概是因为派斯已经在上下文中,我猜?

I tested the following code, but it doesn't work. It throws an exception: "An object with the same key already exists in the ObjectStateManager. The ObjectStateManager cannot track multiple objects with the same key." Probably because Pais is already in the context, I guess?

我使用的是实体(由EF创建)类上下文。另外,我不知道什么是方法输入,我不知道它在哪里。只是为了好玩,我测试:

I'm using a Entities (created by EF) class as context. Also, I don't know what is the method Entry, and I don't know where is it. Just for "fun", I tested this:

// Attach the Pais referenced on editedUF, since editedUF has the new Pais ID, not the old one.
Pais existingPais = new Pais { Codigo = editedUF.Pais.Codigo };
db.Paises.Attach(existingPais);

// Attach the edited UF.
db.UFs.Attach(editedUF);

// Set the correct Pais reference (ignoring the current almost-null one).
editedUF.Pais = existingPais;

// Change the object state to modified.
db.ObjectStateManager.ChangeObjectState(editedUF, EntityState.Modified);

// Save changes.
db.SaveChanges();

return this.ClosePage();

当我尝试了editedUF附加到当前上下文中的异常倒掉。我现在有这个想法的工作,试图找到其他的解决办法。此外,你说得对BennyM,附加的派斯上下文不产生额外的选择。我不知道发生了什么的时候,它确实没有做的任何数据库

The exception is throwed when I try to attach the editedUF to the current context. I'm working with this idea right now, trying to find other solutions. Also, you're right BennyM, attaching the Pais to the context is not generating an additional SELECT. I don't know what happened that time, it really doesn't do anything with the database.

不过,这是一个手动的解决方案:我必须这样做,对于每个FK。这就是我试图避免的。你看,一些程序员,即使你解释的100倍,不会记得这样做与的每个的FK。最终,这会回来给我,所以我试图避免任何可能导致走入误区(数据库或code的),以确保每个人都可以没有任何压力的工作。 :)

Still, this is a manual solution: I have to do that for each FK. That's what I'm trying to avoid. You see, some programmers, even if you explain 100 times, won't remember to do that with each FK. Eventually that'll come back to me, so I'm trying to avoid anything that can lead into errors (database or code ones) to make sure everyone can work without any stress. :)

推荐答案

我回答我的问题,因为我已经找到了一个简单的解决方案(至少在我的情况)。我的情况下使用了大量的访问量数据输入的(这意味着我有很多的实体)。我需要一个简单易用的解决方案,所以我删除了我的整个实体EDMX文件(Ctrl + A键,删除!)。

I'm answering my own question because I've found a simple solution (at least in my case). My scenario uses a lot of Views for data input (which means that I have a lot of entities). I needed a simple and easy to use solution, so I deleted my entire Entities EDMX file (Ctrl+A, Delete!).

然后,我决定再次添加派斯 UF 的实体,但检查暴露FK属性的复选框。在第一次我虽然他们无法一起工作,但他们可以,但你需要了解如何使用它小心一点。他们现在与导航属性相连,暴露的FK。

Then I decided to add again Pais and UF entities, but checking the checkbox for exposing the FK attribute. On first I though they can't work together, but they can, but you need to be a little careful on how to use it. They're now linked with navigation properties and the exposed FK.

我不能添加FK属性的原因是因为我是做手工。 从数据库更新模式使用再次核对正确的选项,它的工作完美无瑕。

The reason I couldn't add the FK attribute is because I was doing it manually. Using the "Update model from database" again checking the correct option it worked flawless.

在我的编辑视图,我设置派斯的ID 进入FK属性,而不是 Pais.Codigo 。为什么我这样做的原因是因为FK属性是标量属性,然后我能察觉的变化。

In my edit view, I'm setting the ID of Pais into the FK attribute, not the Pais.Codigo. The reason why I do that is because the FK attribute is a scalar property and then I can detect changes.

这是当前视图code为派斯输入(它不完全是,但它是与此类似):

This is the current view code for the Pais input (it's not exactly it, but it's similar to this):

@Html.EditorFor(m => m.PaisCodigo)

顺便说一句, PaisCodigo 是FK。是的,它可以得到一点点与 Pais.Codigo 混乱,但我们没有任何决定命名规则(还)。这个想法任何建议将是AP preciated。

Btw, PaisCodigo is the FK. Yes, it can get a little confusing with Pais.Codigo, but we didn't decided any naming rules (yet). Any suggestions on this idea would be appreciated.

最后修改操作code是这样的(我删除了错误的处理,使其看起来简单!)

The final Edit action code is like this (I removed error processing to make it look simple!):

[HttpPost]
public ActionResult Edit(UF editedUF)
{
    if (ModelState.IsValid)
    {
        // Attach the edited UF into the context and change the state to Modified.
        db.UFs.Attach(editedUF);
        db.ObjectStateManager.ChangeObjectState(editedUF, EntityState.Modified);

        // Save changes.
        db.SaveChanges();

        // Call an extension (it's a redirect action to another page, just ignore it).
        return this.ClosePage();
    }
}

这是当我提交表单收到什么 editedUF

This is what is received when I submit the form for editedUF:

{TOTALWeb.UF}
base {System.Data.Objects.DataClasses.EntityObject}: {TOTALWeb.UF}
(...)
CodigoGIA: 0
CodigoIBGE: 0
CodigoPais: 0 <-- new Pais ID!
Descricao: "Foobar 2000"
ID: 902
Pais: {TOTALWeb.Pais}
PaisReference: {System.Data.Objects.DataClasses.EntityReference<TOTALWeb.Pais>}
Sigla: "RI"
Usuarios: {System.Data.Objects.DataClasses.EntityCollection<TOTALWeb.Usuario>}

正如你所看到的, CodigoPais 指向新的派斯 ID。

关于 editedUF.Pais 导航属性,有一个小细节。它连接到上下文之前,它的的。但是,嘿,加入后,这是发生了什么:

About the editedUF.Pais navigation property, there's a small detail. Before attaching it into the context, it's null. But, hey, after adding, this is what happens:

{TOTALWeb.Pais}
base {System.Data.Objects.DataClasses.EntityObject}: {TOTALWeb.Pais}
(...)
Codigo: 0
CodigoBACEN: 1058
CodigoGIA: 0
CodigoIBGE: null
Descricao: "Brasil"
UFs: {System.Data.Objects.DataClasses.EntityCollection<TOTALWeb.UF>}

因此​​,它已被填充。该费用应是一个查询,但我无法捕捉到它在显示器上。

So, it has been filled. The cost for that should be one query, but I couldn't capture it on the monitor.

换句话说,只露出FK,使用视图改变它,使用导航属性,使code更加清楚一点。而已! :)

In other words, just expose the FK, change it using the View and use the navigation property to make the code a little more clear. That's it! :)

谢谢大家,

里卡多

PS:我使用 dotConnect为Oracle 的作为EF 4.1的魅力。我们不使用SQL Server(至少目前如此)。 监视器我说的是devArt的dbMonitor之前,这样我就可以看到发送到Oracle数据库中所有的查询。并再次,对不起任何英文错误!

PS: I'm using dotConnect for Oracle as a base for the EF 4.1. We don't use SQL Server (at least for now). The "monitor" I said before was devArt's dbMonitor, so I can see all queries sent to the Oracle database. And, again, sorry for any english mistakes!

这篇关于ASP.NET MVC与EF 4.1导航性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆