2017-02-19 3 views
0

Итак, это link, показывает, как передать массив int хранимой процедуре.Что такое эквивалентный передающий массив int для хранимой процедуры .net 4.6. Для ядра .net?

CREATE TYPE dbo.EmployeeList 
AS TABLE 
(
    EmployeeID INT 
); 
GO 

CREATE PROCEDURE dbo.DoSomethingWithEmployees 
    @List AS dbo.EmployeeList READONLY 
AS 
BEGIN 
    SET NOCOUNT ON; 

    SELECT EmployeeID FROM @List; 
END 
GO 

и C# Код:

DataTable tvp = new DataTable(); 
// define/populate DataTable from your List here 

using (conn) 
{ 
    SqlCommand cmd = new SqlCommand("dbo.DoSomethingWithEmployees", conn); 
    cmd.CommandType = CommandType.StoredProcedure; 
    SqlParameter tvparam = cmd.Parameters.AddWithValue("@List", tvp); 
    tvparam.SqlDbType = SqlDbType.Structured; 
    // execute query, consume results, etc. here 
} 

Но поскольку ядра .net не поддерживает DataTable, что бы эквивалентный код для .net ядра? Особенно добавляем переменную tvp в качестве параметра в методе AddWithValue, а также последнюю строку кода, которая является tvparam.SqlDbType = SqlDbType.Structured?

Редактировать

Так что я эту хранимую процедуру, которая принимает три параметра. @StudentIds - это массив int.

ALTER PROCEDURE stp_Student 

@Name nvarchar(450), 
@StudentIds tvp_ArrayInt READONLY, 
@StartDate date 

AS 

blah blah 

//returns student summary 
SELECT stu.StudentId, 
     stu.StudentName, 
     CASE WHEN (COUNT(DISTINCT course.Id) IS NOT NULL) THEN COUNT(DISTINCT course.Id) ELSE 0 END AS CourseCount, 
     CASE WHEN (SUM(course.TotalCourses) IS NOT NULL) THEN SUM(course.TotalCourses) ELSE 0 END AS TotalCourses, 
     CASE WHEN (SUM(course.Hours) IS NOT NULL) THEN SUM(course.Hours) ELSE 0 END AS Hours 
FROM #TempStudent AS #Temp 

и на основе вашей рекомендации, я пытался сделать это в контроллере:

public ActionResult Submit(string name, int[] studentIds, DateTime startDate) 
{ 
    context.Database.ExecuteSqlCommand(@"CREATE TYPE dbo_ArrayInt AS TABLE (intValue Int);"); 

    var tvp = new TableValuedParameterBuilder("dbo_ArrayInt", new SqlMetaData("intValue", SqlDbType.Int)) 
      .AddRow(1) 
      .AddRow(2) 
      .CreateParameter("StudentIds"); 

    //But here, I'm not sure how to use tvp variable appropriately 
    var query = _context.Set<StudentModel>().FromSql("dbo.stp_Student @Name = {0}, @StudentIds = {1}, @StartDate = {2}" 
      , name, studentIds, startDate).ToList(); 

Entity для отображения результата:

public class StudentModel 
{ 
    [Key] 
    public long RowId { get; set; } 
    public int StudentId { get; set; }  
    public string StudentName { get; set; } 
    public int CourseCount { get; set; } 
    [Column(TypeName = "Money")] 
    public decimal TotalCourses { get; set; } 
    public double Hours { get; set; } 
} 

ответ

1

Вот полный, самодостаточными пример на .net ядра:

SCHEMA

CREATE TABLE dbo.Students (
    StudentId int NOT NULL, 
    StudentName varchar(50) NOT NULL 
) ON [PRIMARY] 
GO 

CREATE TYPE dbo.ArrayInt 
AS TABLE 
(
    intValue INT 
); 
GO 

CREATE PROCEDURE dbo.stp_Student 
    @Name nvarchar(450), 
    @StudentIds dbo.ArrayInt READONLY, 
    @StartDate date 
AS 
    SELECT 
     StudentId, 
     StudentName, 
     3 AS CourseCount, 
     6 AS TotalCourses, 
     9 AS [Hours] 
    FROM 
     dbo.Students A 
     JOIN @StudentIds B ON A.StudentId = B.intValue 

КОД

using Microsoft.SqlServer.Server; 
using System; 
using System.Collections.Generic; 
using System.ComponentModel.DataAnnotations; 
using System.ComponentModel.DataAnnotations.Schema; 
using System.Data; 
using System.Data.SqlClient; 

namespace StackOverflow.TpvConsole 
{ 
    public class Program 
    { 
     private const String SqlConnetionString = @"Server={Server};Database={Database};User={User};Password={Password};"; 

     public static void Main(String[] args) 
     { 
      var model = new List<StudentModel>(); 

      var parameter = new SqlParameter("StudentIds", SqlDbType.Structured) 
      { 
       Direction = ParameterDirection.Input, 
       TypeName = "dbo.ArrayInt" 
      }; 

      var items = new List<SqlDataRecord>(); 

      //just a quick loop to add three student ids 
      for (var i = 1; i < 4; i++) 
      { 
       var rec = new SqlDataRecord(new SqlMetaData("intValue", SqlDbType.Int)); 
       rec.SetInt32(0, i); 
       items.Add(rec); 
      } 

      parameter.Value = items; 

      using (var db = new SqlConnection(SqlConnetionString)) 
      { 
       var sqlCommand = new SqlCommand("dbo.stp_Student", db) {CommandType = CommandType.StoredProcedure}; 

       sqlCommand.Parameters.Add(new SqlParameter("Name", "Student Name")); 
       sqlCommand.Parameters.Add(parameter); 
       sqlCommand.Parameters.Add(new SqlParameter("StartDate", new DateTime(2016, 8, 1))); 

       db.Open(); 

       var reader = sqlCommand.ExecuteReader(); 

       while (reader.Read()) 
       { 
        model.Add(new StudentModel 
        { 
         StudentId = reader.GetInt32(0), 
         StudentName = reader.GetString(1), 
         CourseCount = reader.GetInt32(2), 
         TotalCourses = reader.GetInt32(3), 
         Hours = reader.GetInt32(4) 
        }); 
       } 
      } 

      foreach (var item in model) 
      { 
       Console.WriteLine($"{item.StudentId}: {item.StudentName}"); 
      } 

      Console.ReadKey(); 
     } 

     public class StudentModel 
     { 
      [Key] 
      public Int64 RowId { get; set; } 
      public Int32 StudentId { get; set; } 
      public String StudentName { get; set; } 
      public Int32 CourseCount { get; set; } 
      [Column(TypeName = "Money")] 
      public Decimal TotalCourses { get; set; } 
      public Double Hours { get; set; } 
     } 
    } 
} 
+0

Спасибо большое! travis – pavilion

+0

Добро пожаловать :-) –

0

Они называются таблицы значений параметров.

According члену группы Entity Framework, вы можете использовать IEnumerable<SqlDataRecord> вместо DataTable. Полностью функциональный gist has been posted.

Смежные вопросы