C#中计算List总字符数,判断是否超出MaxJsonLength上限
首先得理清核心问题:你现在的思路是通过ToString()获取实体内容,但EF的动态代理类默认的ToString()只会返回类名(就是你看到的System.Data.Entity.DynamicProxies.ProductNew_xxx),这根本不是实体的实际数据;而且你尝试直接foreach遍历ProductNew实例报错,是因为它是单个实体对象,不是可枚举的集合,自然没有GetEnumerator方法。
更重要的是:你的最终目的是判断返回的Json是否超过MaxJsonLength,那直接统计Json序列化后的字符串长度才是最准确的,因为ToString()的结果和Json序列化的内容完全不是一回事,之前的统计逻辑从根源上就偏离了目标。
下面给你几个可行的解决方案:
方案一:直接序列化列表获取真实Json长度(推荐)
既然要判断Json的长度,不如直接模拟框架的序列化过程,拿到实际的Json字符串后取长度。这里以常用的Newtonsoft.Json为例(用System.Text.Json逻辑类似):
using Newtonsoft.Json; public JsonResult GetAllProducts() { List<ProductNew> allProducts = _db.Products .Where(p => p.Category.ShopId == 2 && p.Availability) .OrderBy(p => p.Description) .ToList(); // 序列化列表为Json字符串,获取真实长度 string json = JsonConvert.SerializeObject(allProducts); int totalJsonLength = json.Length; // 这里可以和MaxJsonLength做比较,比如: // int maxLength = new JsonResult().MaxJsonLength; // if(totalJsonLength > maxLength) { /* 超出长度的处理逻辑 */ } return new JsonResult { Data = allProducts, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; }
这个方法最直接,得到的长度就是最终返回给前端的Json的真实长度,完全匹配你的需求。
方案二:关闭EF动态代理(如果不需要延迟加载)
如果你只是想让value.ToString()返回实体的内容(但还是要强调,这对统计Json长度没用),可以关闭EF的动态代理,这样查询出来的就是真正的ProductNew实例,而非代理类。你可以在DbContext的构造函数里全局设置:
public YourDbContext() : base("YourConnectionString") { this.Configuration.ProxyCreationEnabled = false; }
或者在单个查询里临时关闭:
allProducts = _db.Products .AsNoTracking() // 同时能提升查询性能 .Where(p => p.Category.ShopId == 2 && p.Availability) .OrderBy(p => p.Description) .ToList();
不过即使关闭了代理,默认的ToString()还是会返回类名,你需要自己重写ProductNew的ToString()方法,比如:
public class ProductNew { // 你的实体属性... public override string ToString() { // 自定义返回内容,比如拼接所有属性 return $"Id: {Id}, Name: {Name}, Description: {Description}"; } }
方案三:用反射遍历实体属性(不推荐,仅作参考)
如果你非要遍历实体的每个属性来计算长度(还是不如直接序列化准确),可以用反射来获取所有公共属性,然后逐个处理:
int total = 0; foreach (var product in allProducts) { // 获取ProductNew的所有公共实例属性 var properties = product.GetType().GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); foreach (var prop in properties) { var value = prop.GetValue(product); if (value != null) { total += value.ToString().Length; } } }
但这个方法有不少问题:比如属性是复杂类型(比如你的Category)时,ToString()还是会返回类名;而且Json序列化会处理null、转义字符等细节,这个统计的长度和真实Json长度差异很大,所以不推荐使用。
内容的提问来源于stack exchange,提问作者valheru

