最近一直用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的值

        public ActionResult EditUser(string id)
        {
            T_SysUser user;
            if (string.IsNullOrEmpty(id))
            {
                user = new T_SysUser();
                user.enabled = true;
            }
            else
            {
                user = asotsDb.T_SysUser.Where(u => u.userid == id).SingleOrDefault();
                if (user == null)
                {
                    throw new Exception("无效的网页地址参数!");
                }
            }

            ViewBag.IsNew = string.IsNullOrEmpty(id);

            return View(user);
        }

        [HttpPost]
        public ActionResult EditUser(string id, T_SysUser model)
        {
            try
            {
                if (string.IsNullOrEmpty(model.userid))
                {
                    ModelState.AddModelError("userid", "用户ID不能为空!");
                }

                if (string.IsNullOrEmpty(id) && string.IsNullOrEmpty(model.password))
                {
                    ModelState.AddModelError("password", "密码不能为空!");
                }
                else if (!string.IsNullOrEmpty(model.password) && model.password.Length < 6)
                {
                    ModelState.AddModelError("password","密码字符串长度必需>=6位!");
                }

                if (string.IsNullOrEmpty(model.employeeid))
                {
                    ModelState.AddModelError("employeeid", "工号不能为空!");
                }

                if (string.IsNullOrEmpty(model.realname))
                {
                    ModelState.AddModelError("realname", "姓名不能为空!");
                }

                if (ModelState.IsValid)
                {
                    var loginedUserInfo = UserBusiness.GetLoginedUserInfo();
                    T_SysUser user = asotsDb.T_SysUser.Where(u => u.userid == model.userid).SingleOrDefault();
                    if (string.IsNullOrEmpty(id))
                    {
                        if (user != null)
                        {
                            ModelState.AddModelError("userid", "该用户ID已经存在!");
                        }
                        else
                        {
                            model.password = Common.GetMD5(model.password);
                            model.lasteupdateby = loginedUserInfo["realname"];
                            model.lasteupdatebyid = loginedUserInfo["userid"];
                            model.lastupdatedatetime = DateTime.Now;
                            asotsDb.T_SysUser.InsertOnSubmit(model);
                        }
                    }
                    else
                    {
                        string oldPassword = user.password;
                        UpdateModel(user);
                        user.password = string.IsNullOrEmpty(model.password) ? oldPassword : Common.GetMD5(model.password);
                        user.lasteupdateby = loginedUserInfo["realname"];
                        user.lasteupdatebyid = loginedUserInfo["userid"];
                        user.lastupdatedatetime = DateTime.Now;
                    }

                    if (ModelState.IsValid)
                    {
                        asotsDb.SubmitChanges();
                        ViewBag.SuccessMsg = "保存成功!";
                        if (string.IsNullOrEmpty(id))
                        {
                            model = new T_SysUser();
                        }
                    }
                }

            }
            catch (Exception ex)
            {
                ModelState.AddModelError("", ex.Message);
            }

            ViewBag.IsNew = string.IsNullOrEmpty(id);

            return View(model);

        }
View Code

相关文章:

  • 2021-06-01
  • 2022-12-23
  • 2022-12-23
  • 2021-07-11
  • 2022-12-23
  • 2021-08-02
  • 2022-03-02
  • 2022-12-23
猜你喜欢
  • 2021-04-22
  • 2022-12-23
  • 2022-12-23
  • 2021-07-10
  • 2021-12-06
  • 2021-10-01
  • 2021-04-14
相关资源
相似解决方案