1.首先我们当看异常堆栈信息
System.Data.EntityCommandExecutionException: 执行命令定义时出错。有关详细信息,请参阅内部异常。 ---> System.Data.SqlClient.SqlException: 列名 'NewPassword' 无效。
在 System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
在 System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
在 System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
在 System.Data.SqlClient.SqlDataReader.TryConsumeMetaData()
在 System.Data.SqlClient.SqlDataReader.get_MetaData()
在 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
在 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds, Boolean describeParameterEncryptionRequest)
在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
在 System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
在 System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
在 System.Data.Common.DbCommand.ExecuteReader(CommandBehavior behavior)
在 System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
--- 内部异常堆栈跟踪的结尾 ---
在 System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand entityCommand, CommandBehavior behavior)
在 System.Data.Objects.Internal.ObjectQueryExecutionPlan.Execute[TResultType](ObjectContext context, ObjectParameterCollection parameterValues)
在 System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
在 System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator()
在 System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source)
在 System.Data.Objects.ELinq.ObjectQueryProvider.<>c__11`1.<GetElementFunction>b__11_1(IEnumerable`1 sequence)
在 System.Data.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
在 System.Data.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[S](Expression expression)
在 System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
在 System.Linq.Queryable.FirstOrDefault[TSource](IQueryable`1 source)
在 GMS.Account.BLL.AccountService.Login(String loginName, String password) 位置 C:\GMS1\Src\GMS.Account.BLL\AccountService.cs:行号 59
在 Castle.Proxies.Invocations.IAccountService_Login.InvokeMethodOnTarget()
在 Castle.DynamicProxy.AbstractInvocation.Proceed()
在 GMS.Core.Service.InvokeInterceptor.Intercept(IInvocation invocation) 位置 C:\GMS1\Src\GMS.Core.Service\ServiceHelper.cs:行号 45
2、通过以上堆栈信息可以知道,是因为列名"NewPassword"无效引起的,这时,可以查看模型类,本例中的模型类如下:
[Auditable]
[Table("User")]
public partial class User : ModelBase
{
public User()
{
Roles = new List<Role>();
IsActive = true;
RoleIds = new List<int>();
}
/// <summary>
/// 登录名
/// </summary>
[Required(ErrorMessage = "登录名不能为空")]
public string LoginName { get; set; }
/// <summary>
/// 密码,使用MD5加密
/// </summary>
[Required]
public string Password { get; set; }
/// <summary>
/// 手机号
/// </summary>
[RegularExpression(@"^[1-9]{1}\d{10}$", ErrorMessage = "不是有效的手机号码")]
public string Mobile { get; set; }
/// <summary>
/// 邮箱
/// </summary>
[RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage = "电子邮件地址无效")]
public string Email { get; set; }
public bool IsActive { get; set; }
/// <summary>
/// 角色列表
/// </summary>
public virtual List<Role> Roles { get; set; }
[NotMapped]
public List<int> RoleIds { get; set; }
[NotMapped]
public string NewPassword { get; set; }
[NotMapped]
public List<EnumBusinessPermission> BusinessPermissionList
{
get
{
var permissions = new List<EnumBusinessPermission>();
foreach (var role in Roles)
{
permissions.AddRange(role.BusinessPermissionList);
}
return permissions.Distinct().ToList();
}
}
}
3、我们可以看到NewPassword属性已经添加了NotMapped,这时,我们可以调试跟踪,查看SQL语句
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[LoginName] AS [LoginName],
[Extent1].[Password] AS [Password],
[Extent1].[Mobile] AS [Mobile],
[Extent1].[Email] AS [Email],
[Extent1].[IsActive] AS [IsActive],
[Extent1].[NewPassword] AS [NewPassword],
[Extent1].[CreateTime] AS [CreateTime]
FROM [dbo].[User] AS [Extent1]
4、注意上面的SQL语句确实多了列名"NewPassword",那我们查看数据库表,看看表中是否存在此列名
5、从上面的截图可以看到,表中确实不存在列名"NewPassword",这时我们可以确定在模型User中的添加的属性"NotMapped"没有起作用,下面就是我的解决方案,
找到DbContext类的派生类,引案例的派生类为DbContextBase,从此派生类中我们双派生另一个类,此类如下:
public class AccountDbContext : DbContextBase
{
public AccountDbContext()
: base(CachedConfigContext.Current.DaoConfig.Account, new LogDbContext())
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<AccountDbContext>(null);
modelBuilder.Entity<User>()
.HasMany(e => e.Roles)
.WithMany(e => e.Users)
.Map(m =>
{
m.ToTable("UserRole");
m.MapLeftKey("UserID");
m.MapRightKey("RoleID");
});
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention>(); modelBuilder.Entity<User>().Ignore(u => u.NewPassword);
}
public DbSet<LoginInfo> LoginInfos { get; set; }
public DbSet<User> Users { get; set; }
public DbSet<Role> Roles { get; set; }
public DbSet<VerifyCode> VerifyCodes { get; set; }
}
6、说明一下,上面类中继承关系是AccountDbContext继承DbContextBase,DbContextBase继承DbContext,在重写方法OnModelCreating中添加方法
modelBuilder.Entity<User>().Ignore(u => u.NewPassword);
这样,就解决了NotMapped无效的问题,即异常列名"NewPassword"无效的问题