【问题标题】:Returning EDM object without references返回没有引用的 EDM 对象
【发布时间】:2014-06-04 11:04:03
【问题描述】:

我已经设置了一个 MVC 4.0 Web API 来处理来自用户的请求,这些请求将从我的数据库中返回信息。

我已经设置并运行了所有控制器、身份验证和接口等,但是在将请求的数据返回给用户时遇到了问题。

我应该注意,我的函数使用并返回 EDM 对象,而不是我自己创建的模型对象。

这是一个示例函数,用户可以GET 数据库中的产品。

public Product Get(int id)
{
        Product product = null;
        try
        {
            using (DataSQLEntities db = new DataSQLEntities())
            {
                product = (from it in db.Products
                               where it.ProductID == id
                               select it).First();                    
            }
        }
        catch (ArgumentNullException)
        {
            var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
            {
                Content = new StringContent(string.Format("No product with id: {0} could be found", id)),
                ReasonPhrase = "Id not found"
            };
            throw new HttpResponseException(resp);
        }
        return product;
}

如果我在返回之前设置断点,该函数可以工作并从数据库返回正确的产品,但是,当涉及通过 APIcontroller 返回产品以进行序列化(Json 或 XML,根据用户请求)时,我得到一个以下错误:

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

这是由于我在代码中使用了using() 语句,当序列化程序尝试“获取”要序列化的对象中的字段值时,它可能需要访问数据库作为value 是对数据库另一部分的引用。但是现在数据库的范围已经消失了,它自然会抛出这个错误。

我一直在寻找防止“产品”对象包含任何引用的方法,但似乎对此知之甚少。

我尝试了其他更改,例如删除 Using 语句,但我真的不想这样做,当我这样做时,由于外键等原因,它返回的数据太多。

我曾尝试更改 LINQ 以试图解决这个问题(见下文),但没有运气、进一步的错误或完全无法管理的代码。对于如何避免在产品中返回引用的任何见解或帮助,我将不胜感激。

替代 LINQ:

这是完全无法管理且糟糕的代码,但有效

var temp = (from it in db.Products
            where it.ProductID == id
            select new
            {
                Name = it.Name,
                Description = it.Description,
                ProductID = it.ProductID
                //Many other fields
            }

return new Product()
           {
               Name = temp.Name,
               Description = temp.Description,
               ProductID = temp.ProductID
               //Many other fields
           }

这不起作用(不是我期望的那样)

Product product = null;
//using here
Product temp = (from it in db.Products
            where it.ProductID == id
            select it).First();
product = temp;
//end using
return product

如果有人能够告诉我如何获取 EDM 对象的字段列表,例如使用反射或类似方法获取普通对象的字段列表,我可能会编写一个函数来循环字段空引用或最小化代码第一个替代 LINQ 代码 sn-p。

非常感谢

【问题讨论】:

  • 也许你可以从你的上下文中分离实体?
  • 您能否提供一些链接或信息,以便我可以更详细地查找?感谢您的评论!
  • 猜测会是这样的db.Entry(product).State = EntityState.Detached;

标签: c# linq object asp.net-web-api


【解决方案1】:

您是否尝试过禁用延迟加载?

db.ContextOptions.LazyLoadingEnabled = false;

【讨论】:

  • 完美运行!正是我正在寻找的东西,但它避开了我!干杯
【解决方案2】:

这是您应该创建视图模型类而不是直接公开域模型的原因之一。

【讨论】:

  • 是的,你是对的,但我们不想担心数据库模型的更改会导致 API 脱节,例如添加或删除列。
  • 那后果自负。这是其中之一,但还会有更多;-)
  • 所以你会建议创建一个模型,它只包含我想要在对象中返回的所有内容,并且每次我在系统的其余部分更新 EDM 时都必须手动更新它?出于好奇,这可能会导致什么其他后果?如果你知道任何在你的头顶?谢谢:)
  • 是的,视图模型背后的整个想法是将 UI 与域对象分离,并且只返回相关数据,而不是对象的整个 grapg。可能出现的另一个问题是序列化递归问题、传递的数据多于所需的网络开销、如果模型更改会破坏外部客户的 api,等等。相信我,没有人愿意为了好玩而编写更多代码,视图模型的想法背后有充分的理由。顺便说一句,使用 Visual Studio 中可用的当前重构工具更新视图模型是微不足道的。
猜你喜欢
  • 2019-05-28
  • 2020-03-03
  • 1970-01-01
  • 2012-09-12
  • 2018-09-16
  • 2018-10-18
  • 1970-01-01
  • 2015-12-17
  • 2021-10-15
相关资源
最近更新 更多