2

I need to know how to call the existing stored procedure in the Entity framework 6 Code First using c#.

Below is the procedure that I am using:

CREATE PROCEDURE proc_getEmployees 
    @departmentname varchar(50),
    @sortCol varchar(30),
    @sortdir varchar(25),
    @searchString varchar(50)
AS
BEGIN
    SET NOCOUNT ON;
    declare @strSQl varchar(1000);
    declare @strSQlwhere varchar(500);
    declare @strSelectEndPart varchar(100);
    
    set @strSQl = ';WITH employeetable as 
                (
                    select ROW_NUMBER() OVER (ORDER BY '+@sortCol+' '+@sortdir+' ) AS RowNumber,COUNT(*) over() as TotalRecords, ID,FirstName,LastName,Designation,DepartmentName,Contact,EmailAddress,Location from Employees ';
    set @strSQlwhere = 'where DepartmentName = '''+@departmentname+'''';
    set @strSQlwhere = @strSQlwhere+ ' and (Id like ''%' + @searchString + '%'' Or FirstName like ''%' + @searchString + '%'' Or LastName like ''%' + @searchString + '%'' Or Designation like ''%' + @searchString + '%'' Or DepartmentName like ''%' + @searchString + '%'' Or Contact like ''%' + @searchString + '%'' Or EmailAddress like ''%' + @searchString + '%'' Or Location like ''%' + @searchString + '%'')';
    set @strSelectEndPart =') select * from employeetable';
                    
    set @strSQl = @strSQl +@strSQlwhere+@strSelectEndPart;
    execute (@strSQl);
END
GO

Table I am querying is Employees having the structure as:

Column          Type    Length
ID              int       4
FirstName       varchar   50
LastName        varchar   50
Designation     varchar   50
DepartmentName  varchar   50
Contact         varchar   50
EmailAddress    varchar   50
Location        varchar   50

DBContext Class is as below:

public class DevelopmentTestDatabaseContext :DbContext
{
    public DevelopmentTestDatabaseContext() : base("name =DevelopmentTestDatabaseContext")
    {

    }
    public virtual DbSet<Employee> EmployeeData { get; set; }
    
}

Method for calling the stored procedure as below:

public void GetEmployeeDataUsingProcedure()
{
    object[] parameters = new SqlParameter[4];
    List<EmployeeResultSet> lstEmployees = new List<EmployeeResultSet>();
    try
    {
        using (var db = new DevelopmentTestDatabaseContext())
        {
            SqlParameter param = new SqlParameter("@departmentname", "IT");
            parameters[0] = param;
            param = new SqlParameter("@sortCol", "ID");
            parameters[1] = param;
            param = new SqlParameter("@sortdir", "asc");
            parameters[2] = param;
            param = new SqlParameter("@searchString", "ope");
            parameters[3] = param;

            var results = db.Database.SqlQuery<EmployeeResultSet>("proc_getEmployees @departmentname, @sortCol, @sortdir, @searchString", parameters);
            db.Database.Log = query => System.Diagnostics.Debug.Write(query);
            lstEmployees = results.ToList();
        }
    }
    catch (Exception ex)
    {

    }
}

Defined the class for the stored procedure resultset as below:

public class EmployeeResultSet
{
    public int rowNumber { get; set; }
    public int totalRecords { get; set; }
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Designation { get; set; }
    public string DepartmentName { get; set; }
    public string Contact { get; set; }
    public string EmailAddress { get; set; }
    public string Location { get; set; }
}

Please, let me know if anything else needs to be done before calling the stored procedure. I am new to EF6 and running into issues. What is missing in the code? Do I need to make some changes in any of the class?

Ravikumar B
  • 779
  • 1
  • 14
  • 25
Puneet Verma
  • 97
  • 2
  • 9
  • If I'm not mistaken, all of your parameters are going to be `new SqlParameter("@searchString", "ope")`. You should do `parameters[0] = new SqlParameter("@key", "value"); parameters[1] = new SqlParameter("@key2", "value2");` and so on. Essentially you are saying `parameters[0]-[4] = param`. Then you change it each line. Therefore you are changing the values in the array. – interesting-name-here Jul 26 '17 at 16:46

2 Answers2

2

One thing I can tell an issue with is in your method where you call the procedure. You are setting all elements of the array equal to param but you are constantly changing param. All of your elements will be equal to the final state of param. Try this instead:

public void GetEmployeeDataUsingProcedure()
{
    object[] parameters = new SqlParameter[4];
    List<EmployeeResultSet> lstEmployees = new List<EmployeeResultSet>();
    try
    {
        using (var db = new DevelopmentTestDatabaseContext())
        {
            parameters[0] = new SqlParameter("@departmentname", "IT");
            parameters[1] = new SqlParameter("@sortCol", "ID");
            parameters[2] = new SqlParameter("@sortdir", "asc");
            parameters[3] = new SqlParameter("@searchString", "ope");

            var results = db.Database.SqlQuery<EmployeeResultSet>("proc_getEmployees @departmentname, @sortCol, @sortdir, @searchString", parameters);
            db.Database.Log = query => System.Diagnostics.Debug.Write(query);
            lstEmployees = results.ToList();
        }
    }
    catch (Exception ex)
    {
        //log it or something
    }
}

There may be other issues but without looking too much into it I'd need more information about specific errors or behavior you are experiencing.

You may also try typing out the full name of your database:

"MyDatabase.MySchema.proc_getEmployees @departmentname, @sortCol, @sortdir, @searchString"

EDIT Per your comments:

A quick ducking and I found this. Essentially it states that if you cast your numbers as int in your query you should be fine. So instead of:

select * from employeetable

Try:

select CAST(RowNumber as int) as RowNumber, 
    CAST(TotalRecords as int) as TotalRecords, 
    CAST(ID as int) as ID, 
    FirstName, 
    LastName, 
    Designation, 
    DepartmentName, 
    Contact, 
    EmailAddress, 
    Location 
from employeetable
interesting-name-here
  • 1,851
  • 1
  • 20
  • 33
  • Thanks for the details, tried the option for parameter mentioned getting the error as The specified cast from a materialized 'System.Int64' type to the 'System.Int32' type is not valid. Also when I try to log the query – Puneet Verma Jul 26 '17 at 17:39
  • hm, maybe try changing your class `int`s to `long`s, see here: https://stackoverflow.com/questions/3845205/how-to-use-int64-in-c-sharp and here: https://stackoverflow.com/questions/32264382/linq-the-specified-cast-from-a-materialized-system-int32-type-to-the-system – interesting-name-here Jul 26 '17 at 17:44
  • Still getting the same error . Also one thing want to clarify as in the statement where I am calling the storedprocedure which is – Puneet Verma Jul 26 '17 at 17:55
  • Still getting the same error . Also one thing want to clarify as I am using EmployeeResultSet while calling procedure in code does this need to be defined in the DevelopmentTestDatabaseContext class as in that I just have one property which is this public virtual DbSet EmployeeData { get; set; } . please let me know if this is problem – Puneet Verma Jul 26 '17 at 18:01
  • No, per the documentation, https://msdn.microsoft.com/en-us/library/system.data.entity.database.sqlquery(v=vs.113).aspx#M:System.Data.Entity.Database.SqlQuery%60%601%28System.String,System.Object[]%29, it can be any type, including non-entities. – interesting-name-here Jul 26 '17 at 18:12
  • thanks a lot for your help , After making changes in the query as per your suggestion it worked perfectly fine. Thanks for all your help. – Puneet Verma Jul 26 '17 at 19:05
  • @PuneetVerma You're welcome. If it helped you reach a resolution, feel free to mark as answer :-) – interesting-name-here Jul 26 '17 at 19:07
  • This is ok but put "exec " before the stored procedure name – Ziregbe Otee Jul 26 '17 at 19:13
  • GibralterTop sorry wasn't aware of marking the answer as accepted so I deleted the comment and accepted your answer hope that works . Thanks for all your help and getting this issue resolved – Puneet Verma Jul 26 '17 at 19:16
  • @ZiregbeOtee actually you do not need it I believe as long as you are SqlServer 2008 or greater: https://stackoverflow.com/a/7518807/5224021 – interesting-name-here Jul 26 '17 at 19:36
0

Something of an aside, but it is not really necessary for you to use dynamic SQL. Particularly when having search criteria being strings it is safer to stick to a parameterised query. In your case you can do something like:

;WITH employeetable as 
(
    select 
    CASE WHEN @sortDir = 'asc' THEN
    ROW_NUMBER() OVER (ORDER BY 
    CASE WHEN @sortCol = 'ID' THEN ID END,
    CASE WHEN @sortCol = 'FirstName' THEN FirstName END,
    CASE WHEN @sortCol = 'LastName' THEN LastName END,
    CASE WHEN @sortCol = 'Designation' THEN Designation END,
    CASE WHEN @sortCol = 'DepartmentName' THEN DepartmentName END,
    CASE WHEN @sortCol = 'Contact' THEN Contact END,
    CASE WHEN @sortCol = 'EmailAddress' THEN EmailAddress END,
    CASE WHEN @sortCol = 'Location' THEN Location END
    ASC) ELSE ROW_NUMBER() OVER (ORDER BY  
    CASE WHEN @sortCol = 'ID' THEN ID END,
    CASE WHEN @sortCol = 'FirstName' THEN FirstName END,
    CASE WHEN @sortCol = 'LastName' THEN LastName END,
    CASE WHEN @sortCol = 'Designation' THEN Designation END,
    CASE WHEN @sortCol = 'DepartmentName' THEN DepartmentName END,
    CASE WHEN @sortCol = 'Contact' THEN Contact END,
    CASE WHEN @sortCol = 'EmailAddress' THEN EmailAddress END,
    CASE WHEN @sortCol = 'Location' THEN Location END
    DESC) END AS RowNumber,
    COUNT(*) over() as TotalRecords, ID,FirstName,LastName,Designation,
    DepartmentName,Contact,EmailAddress,Location from Employees
    where DepartmentName = @departmentname and 
    (Id like '%' + @searchString + '%' Or FirstName like '%' 
    + @searchString + '%' Or LastName like '%' + @searchString + '%' 
    Or Designation like '%' + @searchString + '%' Or 
    DepartmentName like '%' + @searchString + '%' Or 
    Contact like '%' + @searchString + '%' Or 
    EmailAddress like '%' + @searchString + '%' Or 
    Location like '%' + @searchString + '%')
)
select * from employeetable
Jonathan Willcock
  • 5,012
  • 3
  • 20
  • 31
  • Thanks for the inputs will make these changes but my issue is that why I am getting error when I am calling stored procedure , procedure is working perfectly fine in the sql server – Puneet Verma Jul 26 '17 at 18:51
  • Error I m getting is The specified cast from a materialized 'System.Int64' type to the 'System.Int32' type is not valid. tried changing the Datatype for the class as well but still no luck – Puneet Verma Jul 26 '17 at 18:52