【问题标题】:data reader is incompatible with the specified. A member of the type, does not have a corresponding column in the data reader with the same name数据读取器与指定的不兼容。类型的成员,在数据读取器中没有对应的同名列
【发布时间】:2018-04-02 21:22:09
【问题描述】:

所以我正在使用存储过程在使用 C# 的测试 MVC 应用程序中将新用户添加到 db。

我不断收到错误,我认为这是因为我将新添加的用户的 ID 返回到数据库,注释掉代码什么也没做 :(,或者更确切地说,它给了我同样的错误但抱怨不同的变量。

有趣的是,它成功添加了一个用户就好了,只是它抛出了一个异常。

我仍然希望将 ID 返回给调用程序,并且我仍然希望使用参数化查询。

代码如下:

#region AddUser
public static bool AddUser(Models.User user)
{
    bool result = false;
    Models.UserRegistrationPasswordsEntities1 db = new Models.UserRegistrationPasswordsEntities1();
    var queryResult = db.Users.SqlQuery(@"EXECUTE uspAddUser @1, @2, @3, @4, @5, @6",
                                        new SqlParameter("1", user.userFirstName),
                                        new SqlParameter("2", user.userLastName),
                                        new SqlParameter("3", user.userName),
                                        new SqlParameter("4", user.userEmail),
                                        new SqlParameter("5", user.userPassword),
                                        new SqlParameter("6", user.userDateOfBirth)).Single();


    // the ternary opertor is pretty awesome
    result = queryResult == null ? false : true;

    return result;
}
#endregion

Model.user 下面:

public partial class User
{
    public int userID { get; set; }

    [Display(Name = "First Name")]
    [DataType(DataType.Text)]
    [Required(AllowEmptyStrings = false, ErrorMessage ="First name required")]
    public string userFirstName { get; set; }

    [Display(Name = "Last Name")]
    [DataType(DataType.Text)]
    [Required(AllowEmptyStrings = false, ErrorMessage = "Last name required")]
    public string userLastName { get; set; }

    [Display(Name = "Username")]
    [DataType(DataType.Text)]
    [Required(AllowEmptyStrings = false, ErrorMessage = "Username required")]
    public string userName { get; set; }

    [Display(Name = "Email")]
    [DataType(DataType.EmailAddress)]
    [Required(AllowEmptyStrings = false, ErrorMessage = "email is required")]
    public string userEmail { get; set; }

    [Display(Name = "Date Of Birth")]
    [DataType(DataType.DateTime)]
    [Required(AllowEmptyStrings = false, ErrorMessage = "Date of Birth is required")]
    [DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
    public DateTime userDateOfBirth { get; set;}


    [Display(Name = "Password")]
    [DataType(DataType.Password)]
    [Required(AllowEmptyStrings = false, ErrorMessage = "Password is required")]
    [MinLength(6, ErrorMessage = "Minimum of 6 characters required")]
    public string userPassword { get; set; }

    [Display(Name = "Confirm Password")]
    [DataType(DataType.Password)]
    [Required(AllowEmptyStrings = false, ErrorMessage = "Confirm password is required")]
    [Compare("userPassword", ErrorMessage = "Confirm password and password do not match")]
    public string userConfirmPassword { get; set; }

    public bool userStatus { get; set; }
    public bool userEmailVerificationStatus { get; set; }

    public System.Guid userActivationCode { get; set; }
}

错误如下:
这是我收到的错误,存储过程代码被注释掉,如下所示。如果我取消注释它会尖叫 userFirstName

数据读取器与指定的“UserRegistrationPasswordsModel.User”不兼容。类型的成员“userID”在数据读取器中没有同名的对应列。

在下面创建表格:

CREATE TABLE [dbo].[Users] (
    [userID]                      INT              IDENTITY (1, 1) NOT NULL,
    [userFirstName]               VARCHAR (50)     NOT NULL,
    [userLastName]                VARCHAR (50)     NOT NULL,
    [userName]                    VARCHAR (50)     NOT NULL,
    [userEmail]                   VARCHAR (50)     NOT NULL,
    [userPassword]                VARCHAR (255)    NOT NULL,
    [userStatus]                  BIT              DEFAULT ((0)) NOT NULL,
    [userEmailVerificationStatus] BIT              DEFAULT ((0)) NOT NULL,
    [userActivationCode]          UNIQUEIDENTIFIER DEFAULT (newid()) NOT NULL,
    [userDateOfBirth]             DATETIME         NOT NULL,
PRIMARY KEY CLUSTERED ([userID] ASC)
);

存储过程如下:
请注意,底部的 SELECT 已被注释掉,因为我认为可能将 ID 返回给调用程序是问题所在。在我的最终解决方案中,如果可能的话,我仍然希望以这种方式将 Id 返回给调用程序。

CREATE PROCEDURE uspAddUser
 @userFirstName                 VARCHAR(50)
,@userLastName                  VARCHAR(50)
,@userName                      VARCHAR(50)
,@userEmail                     VARCHAR(50)
,@userPassword                  VARCHAR(100)
,@userDateOfBirth               DATETIME

AS
SET NOCOUNT ON      -- Report Only Errors
SET XACT_ABORT ON   -- Rollback transaction on error

BEGIN TRANSACTION

DECLARE @userID  INTEGER

-- CREATE new record
INSERT INTO Users(userFirstName, userLastName, userName, userEmail, userPassword, userStatus, userEmailVerificationStatus, userDateOfBirth)
VALUES(@userFirstName, @userLastName, @userName, @userEmail, @userPassword, 0 ,0, @userDateOfBirth)  -- 1 = Active

---- return ID to calling program
--SELECT UserID FROM Users WHERE userFirstName = @userFirstName AND
--                             userLastName = @userLastName   AND
--                             userName = @userName           AND
--                             userEmail = @userEmail

COMMIT TRANSACTION

我在以下搜索解决方案时访问的资源:
Exception : Execute Insert Stored Procedure using Entity framework ExecuteStoreQuery function

https://blogs.msdn.microsoft.com/diego/2012/01/09/stored-procedures-with-output-parameters-using-sqlquery-in-the-dbcontext-api/

Get return value from stored procedure

Using Entity Framework, should I use RETURN or SELECT in my stored procedures?

感谢您的任何帮助,谢谢。

【问题讨论】:

  • 您是否尝试过在 C# 用户模型中将属性 [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 放在 userID 上?
  • 尝试返回完整的实体,而不仅仅是单个 userID(请注意,传递给 db.Users 的列名必须与从 SP 传递的列具有完全相同的名称)。还将[Key][DatabaseGenerated(DatabaseGeneratedOption.Identity)] 放在userId 属性之上。
  • 感谢您提供有关 [key] 和 [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 的提示。反正有没有只返回ID?如果需要,我还更新了上述错误的描述以包含更多信息。
  • 旁注:虽然您发现条件运算符非常棒,但您可以在这里编写更简单的代码:return queryResult != null;

标签: c# sql-server entity-framework stored-procedures


【解决方案1】:

作为一般规则,当使用SELECT 语句和SqlQuery 方法(而不是单个属性)时,您需要返回full part of the entity。将存储过程中的SELECT 语句更改为:

SELECT TOP 1 * FROM Users 
WHERE userFirstName = @userFirstName AND userLastName = @userLastName 
AND userName = @userName AND userEmail = @userEmail

然后,执行到queryResult

var queryResult = db.Users.SqlQuery(@"EXECUTE uspAddUser @1, @2, @3, @4, @5, @6",
                                        new SqlParameter("1", user.userFirstName),
                                        new SqlParameter("2", user.userLastName),
                                        new SqlParameter("3", user.userName),
                                        new SqlParameter("4", user.userEmail),
                                        new SqlParameter("5", user.userPassword),
                                        new SqlParameter("6", user.userDateOfBirth)).Single();

如果你想从AddUser方法中获取userID,你可以从上面的查询结果中调用它(并将返回类型改为int而不是bool):

int userId = queryResult.userID;

return userId;

旁注:

由于userID被声明为主键标识列,所以在EF模型类中将KeyAttributeDatabaseGeneratedAttribute设置对应的属性为主键:

public partial class User
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int userID { get; set; }

    // other properties

}

类似问题:

does not have a corresponding column in the data reader with the same name

【讨论】:

  • 这是我的回答。非常感谢,我想我必须习惯这就是它在实体框架中的工作方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-09-11
  • 1970-01-01
  • 1970-01-01
  • 2021-02-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多