关于ASP.NET MVC开发设计中出现的问题与解决方案汇总 【持续更新】

简介:

最近一直用ASP.NET MVC 4.0 +LINQ TO SQL来开发设计公司内部多个业务系统网站,在这其中发现了一些问题,也花了不少时间来查找相关资料或请教高人,最终都还算解决了,现在我将这些问题及对应的解决方案都整理汇总出来,供大家参供,有不对之处或有更好的解决办法,欢迎在本文评论,谢谢!

【2014-12-2发布】

问题一:执行类似语句:dbDataContext.TableName.Join(modelList as List<实体对象类型>,t1=>t1.id,t2=>t2.id,(t1,t2)=>new{属性赋值}),报错:不能在查询运算符(Contains 运算符除外)的 LINQ to SQL 实现中使用本地序列。

原因分析:数据表映射实体对象无法与C#自有集合对象关联查询,必需确保LINQ 语句进行查询与运算均为数据表映射实体对象或C#自有集合对象

解决方案:dbDataContext.TableName.Join(dbDataContext.TableName2,t1=>t1.id,t2=>t2.id,(t1,t2)=>new{属性赋值}),或dbDataContext.TableName.AsEnumerable().Join(modelList as List<实体对象类型>,t1=>t1.id,t2=>t2.id,(t1,t2)=>new{属性赋值}),但后者存在性能问题,因为AsEnumerable()就会立即执行查询动作,将TableName中所有的数据加载到本地内存中后才去与后面的modelList 关联。

 

问题二:执行类似语句:dbDataContext.TableName.Select(t=>new 数据表映射实体类{属性赋值}),报错:不允许在查询中显式构造实体类型“XXXXXXXXX”。

原因分析:摘自网络上的原话“LINQ to SQL在RTM之前的版本有个Bug,如果在查询中显式构造一个实体的话,在某些情况下会得到一系列完全相同的对象。很可惜这个Bug我只在资料中看到过,而在RTM版本的LINQ to SQL中这个Bug已经被修补了,确切地说是绕过了。直接抛出异常不失为一种“解决问题”的办法,虽然这实际上是去除了一个功能——没有功能自然不会有Bug,就像没有头就不会头痛了一个道理。”

解决方案:1.将Select(t=>new 数据表映射实体类{属性赋值})改为直接返回匿名类:Select(t=>new {属性赋值}),或重新定义该实体类对象,去掉与数据表映射相关的特性,即:Select(t=>new 自定义实体类{属性赋值}),2.利用LINQ to SQL中DataContext提供有GetCommand方法,扩展方法ExecuteQuery<T>,代码如下:

复制代码
public static class DataContextExtensions
{
    public static List<T> ExecuteQuery<T>(this DataContext dataContext, IQueryable query)
    {
        DbCommand command = dataContext.GetCommand(query);
        dataContext.OpenConnection();
 
        using (DbDataReader reader = command.ExecuteReader())
        {
            return dataContext.Translate<T>(reader).ToList();
        }
    }
 
    private static void OpenConnection(this DataContext dataContext)
    {
        if (dataContext.Connection.State == ConnectionState.Closed)
        {
            dataContext.Connection.Open();
        }
    }
}
复制代码

在执行的时候就可以先以LINQ查询,然后执行ExecuteQuery方法,如:

var query=dbDataContext.TableName.Select();
var modelList=dbDataContext.ExecuteQuery<数据表映射实体类>(query);

问题三:使用ModelState.AddModelError(“字段名”,“错误信息”)添加多个信息时,在VIEW中用Html.ValidationSummary(false) 显示的报错顺序不一定与AddModelError的先后顺序相同,即:

ModelState.AddModelError(“字段名1”,“错误信息1”);
ModelState.AddModelError(“字段名9”,“错误信息2”);
ModelState.AddModelError(“字段名6”,“错误信息3”);
ModelState.AddModelError(“字段名3”,“错误信息4”);
ModelState.AddModelError(“字段名5”,“错误信息5”);

显示出来可能是(无序的或以字段名排序后显示):

错误信息1
错误信息4
错误信息5
错误信息3
错误信息9

这就明显会影响用户体验,所以建议使用以下方法,这样显示出来的错误就是正常的,原理很简单,因为若ModelState.AddModelError为同一个键,此处为空,则会在该键的ModelState.Errors下添加项,而由于Errors最终存为List类型,所以索引顺序也就确定了

ModelState.AddModelError(“”,“错误信息1”);
ModelState.AddModelError(“”,“错误信息2”);
ModelState.AddModelError(“”,“错误信息3”);
ModelState.AddModelError(“”,“错误信息4”);
ModelState.AddModelError(“”,“错误信息5”);

 

问题四:将匿名对象作为Model数据传给View并显示时,报错:“object”不包含“XXX”的定义。

原因分析:匿名类型默认访问修饰符为internal,这意味着他们只可以从其定义的程序集中被访问。一旦你超越了程序集的边界,将会被当做普通的object对象被解析,因此不具备直接索引属性。

解决方案:1.使用Tuple元组静态类,即:

复制代码
Controller中:
var
result= dbDataContext.TableName.Select(s=>Tuple.Create(参数赋值)); View中使用: @model IEnumerable<dynamic> foreach (var item in Model) { <tr> <td>@item.Item1</td> <td>@item.Item2</td> <td>@item.Item3</td> <td>@item.Item4</td> <td>@item.Item5</td> </tr> }
复制代码

2.还可以使用ExpandoObject类,这是.NET 4.0中的一种类型:ExpandoObject,ExpandoObject类型是一种可以再运行时随意动态添加和删除成员的类型。

复制代码
 
 
Controller中:
public ActionResult UsingExpando()  
{  
    dynamic viewModel = new ExpandoObject();  
    viewModel.TestString = "This is a test string";  
   
    return View(viewModel);  
}  

View中使用:

<p> @Model.TestString </p>
复制代码

 

【2014-12-09发布】

问题五:从视图页面接收到MODEL对象后(POST到ACTION),对MODEL对象各属性进行变更并重新传给视图显示,但显示的结果仍然是之前视图上编辑的MODEL的值

  View Code
  View Code

原因分析:初步认为是当ModelState中有键值时,在使用View(model)或ViewData.Model=model时,系统自动会将ModelState与model对象进行映射并更新,造成了不论你如何变更model对象的各属性值,最终显示到视图时,仍是显示上次视图界面的值,有点类似webform中的viewstate,当然这个只是我的猜测,若哪位高手知道其原理还望告之。

解决方案:在重新创建model对象后,1.若要清除model对象中某个属性的值,则可以使用:ModelState.Remove("Model属性名称"),

2.若要清除model对象所有属性的值,则可以使用:ModelState.Clear()

 

问题六:使用LINQ TO SQL附加MODEL对象并执行更新或删除时(如:dbDataContext.T_SysUser.Attach(user); dbDataContext.SubmitChanges();),报错:已尝试Attach或Add实体,该实体不是新实体,可能是从其他DataContext中加载来的。不支持这种操作。

 原因分析:详见使用LINQ to SQL更新数据库(上):问题重重

解决方案:详见使用LINQ to SQL更新数据库(中):几种解决方案,我一直采用的是重新赋值,如下:

T_SysUser user = asotsDb.T_SysUser.Where(u => u.userid == model.userid).SingleOrDefault();
UpdateModel(user);

 

【2014-12-17】 

问题七:当使用JQuery AJAX POST数组到ACTION时,ACTION无法直接接收该数组信息

原因分析:用JQuery.Ajax 提交Array的数据,提交的时候始终会在名称后面加上”[]”

解决方案:1.若是普通的数组,比如:字符串数组、数字数组,则可使用如下方法:

复制代码
        [HttpPost]
        public ActionResult Test(FormCollection form)
        {
             string[] userRoles = form.GetValues("params[]");//这里就可以直接获取AJAX POST过来的数组
            
            return View();
        }
复制代码

2.若是复杂类型或对象数组,则可使用如下方法:

[HttpPost]
public ActionResult Test(FormCollection form)
{
    var models=form.GetValues("params[]").Select(p=>p.Single<Model>()).ToArray();
}

或自定义继承DefaultModelBinder的一个类,并重写BindModel方法:

复制代码
    public class JQAjaxModelBinder : DefaultModelBinder
    {

        public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
        {
            if (bindingContext.ModelType.IsArray) //判断是否为数组
            {
                var key = bindingContext.ModelName + "[]";
                var valueResult = bindingContext.ValueProvider.GetValue(key);
                if (valueResult != null && !string.IsNullOrEmpty(valueResult.AttemptedValue))
                {
                    bindingContext.ModelName = key;
                }
            }
            return base.BindModel(controllerContext, bindingContext);
        }
    }
复制代码

在ACTION中可以如下使用:

复制代码
        [HttpPost]
        public ActionResult Test([ModelBinder(typeof(JQAjaxModelBinder))] Model[] models)
        {
             Model model=models[0]; //这里举例获取数组中某个对象
             model.name="zuowenjun";
             model.sex=1;
             model.url="www.zuowenjun.cn";
            return View();
        }
复制代码

 

【2015-03-06】

 问题七:ObjectStateManager 中已存在具有同一键的对象。ObjectStateManager 无法跟踪具有相同键的多个对象。

原因分析:对象的实体状态已处于了 deattach状态;

解决方案:查询的时候加上asNoTracking(),然后在进行更新或删除时,使用Attach即可;

 

后续若还有新的问题,会持续更新,工作中学习,学习中总结,总结后实践,实践后掌握!

本文转自 梦在旅途 博客园博客,原文链接:http://www.cnblogs.com/zuowj/p/4137221.html ,如需转载请自行联系原作者


相关文章
|
3月前
|
API C++ Windows
Visual C++运行库、.NET Framework和DirectX运行库的作用及常见问题解决方案,涵盖MSVCP140.dll丢失、0xc000007b错误等典型故障的修复方法
本文介绍Visual C++运行库、.NET Framework和DirectX运行库的作用及常见问题解决方案,涵盖MSVCP140.dll丢失、0xc000007b错误等典型故障的修复方法,提供官方下载链接与系统修复工具使用指南。
884 2
|
XML JSON API
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
844 3
|
设计模式 开发框架 JavaScript
基于.NET8 + Vue/UniApp前后端分离的快速开发框架,开箱即用!
基于.NET8 + Vue/UniApp前后端分离的快速开发框架,开箱即用!
438 0
|
11月前
|
监控 Linux
yum install -y net-snmp-devel 安装不成功 zabbix项目安装,Errors during downloading metadata for repository ‘extras-common’:问题解决方案-优雅草卓伊凡
yum install -y net-snmp-devel 安装不成功 zabbix项目安装,Errors during downloading metadata for repository ‘extras-common’:问题解决方案-优雅草卓伊凡
562 13
yum install -y net-snmp-devel 安装不成功 zabbix项目安装,Errors during downloading metadata for repository ‘extras-common’:问题解决方案-优雅草卓伊凡
|
11月前
|
人工智能 芯片
D1net阅闻|OpenAI员工疯狂暗示,内部已成功开发ASI?被曝训出GPT-5但雪藏
D1net阅闻|OpenAI员工疯狂暗示,内部已成功开发ASI?被曝训出GPT-5但雪藏
|
9月前
|
SQL 小程序 API
如何运用C#.NET技术快速开发一套掌上医院系统?
本方案基于C#.NET技术快速构建掌上医院系统,结合模块化开发理念与医院信息化需求。核心功能涵盖用户端的预约挂号、在线问诊、报告查询等,以及管理端的排班管理和数据统计。采用.NET Core Web API与uni-app实现前后端分离,支持跨平台小程序开发。数据库选用SQL Server 2012,并通过读写分离与索引优化提升性能。部署方案包括Windows Server与负载均衡设计,确保高可用性。同时针对API差异、数据库老化及高并发等问题制定应对措施,保障系统稳定运行。推荐使用Postman、Redgate等工具辅助开发,提升效率与质量。
397 0
|
缓存 算法 安全
精选10款C#/.NET开发必备类库(含使用教程),工作效率提升利器!
精选10款C#/.NET开发必备类库(含使用教程),工作效率提升利器!
504 12
|
Linux API C#
基于 .NET 开发的多功能流媒体管理控制平台
基于 .NET 开发的多功能流媒体管理控制平台
235 9
|
Web App开发 前端开发 调度
一款基于 .NET + Blazor 开发的智能访客管理系统
一款基于 .NET + Blazor 开发的智能访客管理系统
208 8
|
前端开发 JavaScript C#
基于.NET8+Vue3开发的权限管理&个人博客系统
基于.NET8+Vue3开发的权限管理&个人博客系统
205 7