在数据库中插入日期时出错

时间:2016-07-20 10:33:15

标签: c# sql-server asp.net-mvc stored-procedures

我正在尝试使用存储过程将数据插入数据库,但是我收到错误。

我存储数据的代码是这样的:

public string InsertJobData(JobDTO jobdata)
    {
        try
        {
            DbManager.OpenConnection();
            DbManager.AddParameter("JobId", jobdata.JobType, StoredProcedureParameterDirection.Input);
            DbManager.AddParameter("JobTypeId", jobdata.JobTypeId, StoredProcedureParameterDirection.Input);

            if (jobdata.JobRefence != null)
            {
                DbManager.AddParameter("JobRefence", jobdata.JobRefence, StoredProcedureParameterDirection.Input);
            }

            else
            {
                DbManager.AddParameter("JobRefence", DBNull.Value, StoredProcedureParameterDirection.Input);
            }

            DbManager.AddParameter("JobName", jobdata.JobName, StoredProcedureParameterDirection.Input);
            DbManager.AddParameter("CustomerName", jobdata.CustomerName, StoredProcedureParameterDirection.Input);
            DbManager.AddParameter("Quantity", jobdata.Quantity, StoredProcedureParameterDirection.Input);
            DbManager.AddParameter("JobDescription", jobdata.JobDescription, StoredProcedureParameterDirection.Input);
            DbManager.AddParameter("CreatedOn", jobdata.CreatedOn, StoredProcedureParameterDirection.Input);

            if (jobdata.CompleteOn != null)
            {
                DbManager.AddParameter("CompleteOn", jobdata.CompleteOn, StoredProcedureParameterDirection.Input);
            }

            else
            {
                DbManager.AddParameter("CompleteOn", DBNull.Value, StoredProcedureParameterDirection.Input);
            }

            DbManager.AddParameter("Department", jobdata.Department, StoredProcedureParameterDirection.Input);
            DbManager.AddParameter("DepartmentId", jobdata.DepartmentId, StoredProcedureParameterDirection.Input);
            DbManager.AddParameter("Status", jobdata.Status, StoredProcedureParameterDirection.Input);

            if (jobdata.AreaOfPCB != null)
            {
                DbManager.AddParameter("AreaOfPCB", jobdata.AreaOfPCB, StoredProcedureParameterDirection.Input);
            }

            else
            {
                DbManager.AddParameter("AreaOfPCB", DBNull.Value, StoredProcedureParameterDirection.Input);
            }


            if (jobdata.NumberOfJoints != null)
            {
                DbManager.AddParameter("NumberOfJoints", jobdata.NumberOfJoints, StoredProcedureParameterDirection.Input);
            }

            else
            {
                DbManager.AddParameter("NumberOfJoints", DBNull.Value, StoredProcedureParameterDirection.Input);
            }

            DbManager.AddParameter("TaskStatus", jobdata.Tasktypeid, StoredProcedureParameterDirection.Input);
            DbManager.AddParameter("Id", StoredProcedureParameterDirection.Output);
            DbManager.ExecuteNonQuery("spInsertJobData", System.Data.CommandType.StoredProcedure);
            jobdata.Id = (int)DbManager.GetParameter("Id");

            jobdata.NewJobId = jobdata.JobType + "_" + jobdata.Id;

            //dbManager.AddParameter("JobId", jobdata.JobType, StoredProcedureParameterDirection.Input);
            //dbManager.ExecuteNonQuery("spUpdateJobByJobId", System.Data.CommandType.StoredProcedure);

        }

        catch
        {

        }

        finally
        {
            DbManager.CloseConnection();
        }

        return jobdata.NewJobId;
    }

我的自豪阶级是这样的:

 public int Id { get; set; }
    public string JobId { get; set; }
    public int JobTypeId { get; set; }
    public string JobRefence { get; set; }
    public string JobName { get; set; }
    public string CustomerName { get; set; }
    public int Quantity { get; set; }
    public string JobDescription { get; set; }
    public DateTime CreatedOn { get; set; }
    public DateTime? CompleteOn { get; set; }
    public string Department { get; set; }
    public int DepartmentId { get; set; }
    public bool Status { get; set; }
    public string JobType { get; set; }
    public string NewJobId { get; set; }
    public float? AreaOfPCB { get; set; }
    public int? NumberOfJoints { get; set; }
    public int? Tasktypeid { get; set; }

我的存储过程是这样的:

`

CREATE procedure [dbo].[spInsertJobData]
@JobId nvarchar(50),
@JobTypeId int,
@JobRefence nvarchar(50),
@JobName nvarchar(50),
@CustomerName nvarchar(50),
@Quantity bigint,
@JobDescription nvarchar(MAX),
@CreatedOn datetime,
@CompleteOn datetime,
@Department nvarchar(50),
@DepartmentId int,
@Status bit,
@AreaOfPCB int,
@NumberOfJoints bigint,
@TaskStatus int,
@Id int OUTPUT
As
BEGIN
INSERT INTO oms.JobId_Table (JobId,JobTypeId,JobRefence,JobName,CustomerName,Quantity,JobDescription,CreatedOn,CompleteOn,Department,DepartmentId,Status,AreaOfPCB,NumberOfJoints,TaskStatus)
VALUES (@JobId,@JobTypeId,@JobRefence,@JobName,@CustomerName,@Quantity,@JobDescription,@CreatedOn,@CompleteOn,@Department,@DepartmentId,@Status,@AreaOfPCB,@NumberOfJoints,@TaskStatus)
UPDATE oms.JobId_Table
SET JobId = 'oms.' + Convert(varchar,@JobId) +'_'+ Convert(varchar,oms.JobId_Table.Id)
WHERE JobId = @JobId
SET @Id = SCOPE_IDENTITY()
RETURN  @Id
END`

当我执行代码时,它抛出以下异常:
enter image description here

请帮忙。 在此先感谢。

有关例外的更多细节:`

System.Data.SqlClient.SqlException was caught
  HResult=-2146232060
  Message=Error converting data type nvarchar to datetime.
  Source=.Net SqlClient Data Provider
  ErrorCode=-2146232060
  Class=16
  LineNumber=0
  Number=8114
  Procedure=spInsertJobData
  Server=JITENDERSINGH\JITENDER
  State=5
  StackTrace:
       at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
       at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
       at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
       at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
       at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
       at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite, SqlDataReader ds)
       at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource`1 completion, Int32 timeout, Task& task, Boolean asyncWrite)
       at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource`1 completion, String methodName, Boolean sendToPipe, Int32 timeout, Boolean asyncWrite)
       at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
       at Company.Project.Entities.Entities.DatabaseHelper.ExecuteNonQuery(String query, CommandType commandtype, DatabaseConnectionState connectionstate) in e:\SGS_MVC_APP\SGS_PROJECT\Company.Project.Entities\Entities\DBHelper.cs:line 258
       at Company.Project.Entities.Entities.DatabaseHelper.ExecuteNonQuery(String query, CommandType commandtype) in e:\SGS_MVC_APP\SGS_PROJECT\Company.Project.Entities\Entities\DBHelper.cs:line 221
       at Company.Project.Entities.Entities.DBManager.ExecuteNonQuery(String query, CommandType commandtype) in e:\SGS_MVC_APP\SGS_PROJECT\Company.Project.Entities\Entities\DBManagerBase.cs:line 131
       at Company.Project.DataAccess.BiddingFirstStepDAC.InsertJobData(JobDTO jobdata) in e:\SGS_MVC_APP\SGS_PROJECT\Company.Project.DataAccess\BiddingFirstStepDAC.cs:line 163
  InnerException: 

`

1 个答案:

答案 0 :(得分:-1)

当你使用通用数据访问层,DbManger,Dbhelper和其他处理参数类型的类,加上存储过程处理许多字符串列时,我很快就解决了这个问题,我的建议是:

  • 使用sql profiller查看从DAL发送到服务器的sql语句。这是你的朋友工具。
  • 查看异常详细信息,并跟踪源代码行以了解错误来源。
  • 非常重要:DAL应该以记录日志文件中的错误的方式处理异常,具有异常详细信息和参数的名称/值/类型,以帮助解决问题。捕获从服务器发送的一般异常是不够的。
  • DAl应该根据服务器的DateTime格式将字符串(DateTime列)转换为DateTime。为了安全起见,YYYYMMDD是标准的,无论客户端区域日期时间的格式如何。
  • 您应该进行单元测试。并在出现新的错误/错误时更新您的测试。

修改

从存储过程的数据类型来看,只有@CreatedOn和@CompleteOn是日期时间类型,因此它们可能是错误的来源。

我猜:这些列的日期时间格式与服务器日期时间格式不匹配 让sql profiler告诉我们发生了什么。

编辑2:

DbManager.AddParameter不会传递参数的sql数据类型,这样可以确保客户端和服务器正确地进行数据转换。 它应该是:

  param.SqlDbType = SqlDbType.DateTime;

作为概念验证,我在c#ado.net应用程序的northwind数据库中运行名为“[按年份销售]”的存储过程并传递参数。

我的SQL Server(sql 2012)日期时间格式为:mdy

获取:运行命令

dbcc useroptions

你得到(在我的情况下)

dateformat  mdy

如果以mdy或ymd(通用格式)传递日期时间,则服务器会接受该错误。

如果以dmy格式(与服务器不同)传递datatime,则会引发错误:

Error converting data type nvarchar to datetime.

我修改了Ending_Date的日期时间格式并运行不同的情况,如下所示:

//   var date2= DateTime.Today.ToString("MMMM dd, yyyy"); //ok match server
//var date2 = DateTime.Today.ToString("dd-MM-yy"); //error don't match server format
var date2 = DateTime.Today.ToString("dd-MM-yyyy"); //error don't match server
var date2 = DateTime.Today.ToString("yyyyMMdd"); //ok universal datetime format

当我查看sql profiler的结果时(一目了然我可以捕获sql并修复错误),我发现:

SQL Profiler的输出:

有效

exec [dbo].[Sales by Year] @Beginning_Date=N'1970/1/1',@Ending_Date=N'July 20, 2016'
exec [dbo].[Sales by Year] @Beginning_Date=N'1970/1/1',@Ending_Date=N'7/20/2016 12:00:00 AM'
exec [dbo].[Sales by Year] @Beginning_Date=N'1970/1/1',@Ending_Date='2016-07-20 00:00:00'
exec [dbo].[Sales by Year] @Beginning_Date=N'1970/1/1',@Ending_Date=N'20160720'

错误无效:

exec [dbo].[Sales by Year] @Beginning_Date=N'1970/1/1',@Ending_Date=N'20-07-2016'

<强>结论:

以服务器的典型格式或通用格式ymd

设置日期时间的变量

因此,请将代码修改为:

DbManager.AddParameter("CreatedOn", jobdata.CreatedOn.ToString("yyyyMMdd"), StoredProcedureParameterDirection.Input);

DbManager.AddParameter("CompleteOn", jobdata.CompleteOn.ToString("yyyyMMdd"), StoredProcedureParameterDirection.Input);

我希望有助于解决您的问题

编辑3:处理空值

您已在代码中处理jobdata.CompleteOn的空值,因此对jobdata.CreatedOn执行相同操作

if (jobdata.CreatedOn != null)
        {
            DbManager.AddParameter("CreatedOn", jobdata.CreatedOn.ToString("yyyyMMdd"), StoredProcedureParameterDirection.Input);
        }
        else
        {
            DbManager.AddParameter("CreatedOn", DBNull.Value, StoredProcedureParameterDirection.Input);
        }

注意:

1)由于jobdata.CreatedOn可能为null,最好使用DateTime将jobdata.CreatedOn声明为可为空?

public DateTime? CreatedOn { get; set; }

2)格式化DateTime的其他方法:

var createon=  string.Format("{0:yyyyMMdd}",jobdata.CreatedOn));