将Entity Framework对象序列化为JSON

8
public class GenericHandler : IHttpHandler
{
    public class ASSystem
    {
        public string SID { get; set; }
        public string Description { get; set; }
        public string SystemName { get; set; }
    }

    public class ErrorObj
    {
        public string ErrorMessage { get; set; }
    }

    public void ProcessRequest(HttpContext context)
    {
        HttpContext.Current.Response.ContentType = "application/json";
        HttpContext.Current.Response.ContentEncoding = Encoding.UTF8;

        string query = HttpContext.Current.Request.QueryString["SID"];


        SOFAEntities ctx = new SOFAEntities();
        JavaScriptSerializer serializer = new JavaScriptSerializer();

        try
        {
            AS_SYSTEM system = ctx.AS_SYSTEM.Where(s => s.SYSTEM_ID == query).First() as AS_SYSTEM;

            if (system != null)
            {
                ASSystem sys = new ASSystem() { SID = system.SYSTEM_ID, Description = system.DESCRIPTION, SystemName = system.SYSTEM_NAME };
                HttpContext.Current.Response.Write(serializer.Serialize(sys));
            }
        }
        catch (Exception e)
        {
            HttpContext.Current.Response.Write(serializer.Serialize(new ErrorObj() { ErrorMessage = e.Message }));
        }





    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

这样做是可以的,但是当我尝试使用HttpContext.Current.Response.Write(serializer.Serialize(system));时,出现了以下错误:

在序列化类型'System.Data.Metadata.Edm.AssociationType'的对象时检测到循环引用。

我想要的是一个代表完整as_system对象的JSON对象,这样我就不必手动映射每个属性了。有什么办法可以解决这个问题吗?谢谢!
5个回答

5
如果您想将Entity Framework对象序列化为JSON格式,可以使用来自http://www.newtonsoft.com的JSON.NET。要实现此操作,请从NuGet安装JSON.NET,并使用以下示例代码:
return Newtonsoft.Json.JsonConvert.SerializeObject(results, Formatting.Indented, 
new JsonSerializerSettings { 
    ReferenceLoopHandling = ReferenceLoopHandling.Ignore 
});

ReferenceLoopHandling.Ignore可以避免循环引用错误。


5
我认为这将防止循环引用,但如果不需要的话,不会阻止不必要地加载相关实体。 - renathy

4
您可以创建一个 POCO 对象来包含您的数据并进行序列化。例如,定义如下:
public class MySystem {
  public int SID {get; set;}
  public string Description {get; set;}
  public string SystemName {get; set;}
}

在你的代码中使用这个语句:
IQuerable<MySystem> sysList = from s in ctx.AS_SYSTEM where s.SYSTEM_ID == query 
                           select new MySystem(){SID = s.SYSTEM_ID,  
                           Description = s.Description, SystemName = s.SystemName   };
MySystem sys = sysList.First();

现在您可以像示例中一样将 sys 序列化。

1
有没有办法让EF生成一个包含所有列及其正确数据类型的属性的类? - Johan
@Johan 是的,EF 4.0支持POCO对象,而EF 4.1默认使用POCO。 - Massimo Zerbini

4
似乎EF没有给你一个ASSystem,而是一些微妙的动态子类,带有一些EF特性。如果这是正确的,我会建议在这里做最简单的事情,就是使用类似AutoMapper的东西来获得一个非EF副本(到一个new ASSystem()实例中,不受EF影响)。然而,还有几个替代方案:
  • 您可以尝试将ASSystem标记为sealed,取消EF注入的能力
  • 您可以编写自定义转换器并进行注册-虽然这可能比映射更费力

0

不确定这是否有帮助,但尝试使用DataContractJsonSerializer而不是JavaScriptSerializer。据我所知,DataContractJsonSerializer比JavaScriptSerializer更受欢迎。


我忘了提到我正在使用.NET 3.5和VS2008。我找不到它,我想这就是问题所在? :) - Johan
我通常发现DataContractJsonSerializer在许多情况下会给出一些有点... 非典型 的JSON。我通常使用JavaScriptSerializerJson.NET更加顺利。 - Marc Gravell

-2

试试这个,对我有效。

返回 JSON 数据 [在 EF 中]:

  1. 将引用 System.Runtime.Serialization 添加到项目中。
  2. 编写以下代码:

using System.Web.Script.Serialization;

    public string getValuesJson()
    {
        JavaScriptSerializer js = new JavaScriptSerializer();
        MyDBEntities ctx = new MyDBEntities();

        var myValues = (from m in ctx.TestEntity
                       where (m.id == 22)
                       select m).ToList();

        return js.Serialize(myValues);
    }

你也可以在http://jsonlint.com/检查JSON字符串是否有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接