Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Limited DateOnly C# support when using SqlParameter.Structured #2209

Closed
PK-ByTE opened this issue Nov 7, 2023 · 3 comments · Fixed by #2258
Closed

Limited DateOnly C# support when using SqlParameter.Structured #2209

PK-ByTE opened this issue Nov 7, 2023 · 3 comments · Fixed by #2258
Labels
💡 Enhancement Issues that are feature requests for the drivers we maintain.

Comments

@PK-ByTE
Copy link

PK-ByTE commented Nov 7, 2023

C# DateOnly not supported when using SqlParameter.Structured (Datatable)

Current .net 8 rc2 works with DateOnly type when passing DateOnly values to sql procedure like so:
image

But if we try to pass the DateOnly as udtt via SqlParameter.Structured we get an error like so:
image

To reproduce

Program.cs

 internal class Program
 {
     static async Task Main(string[] args)
     {
         var x = new TestAppSimple();
         await x.TestDataGet(); 
     }
 }

TestAppSimple.cs

 internal class TestAppSimple
{
    private SqlConnection Connection { get; set; }

    public TestAppSimple()
    {
        var connectionString = "Server=localhost;..."; 
        Connection = new SqlConnection(connectionString);

    }

    public async Task TestDataGet()
    {
        try
        {
            Connection.Open();

            await TryToPassDateOnlyAsParamSimple(); //Works!
            await TryToPassDateOnlyAsStructuredParamSimple(); //Fails!
        }
        catch(Exception e)
        {
            Console.WriteLine(e.Message);
        }
        finally
        {
            Connection?.Close();
            Connection?.Dispose();
        }
    }

    #region Sql tests

    private async Task TryToPassDateOnlyAsParamSimple()
    {
        try
        {
            var command = Connection.CreateCommand();
            command.CommandText = "[dbo].[spTestDateOnly]";
            command.CommandTimeout = 30;
            command.CommandType = CommandType.StoredProcedure;
            command.Parameters.Add(new SqlParameter
            {
                ParameterName = "@date",
                SqlDbType = SqlDbType.Date,
                Value = new DateOnly(2023, 11, 15)
            });

            using (var reader = await command.ExecuteReaderAsync())
            {
                //if passes here, then it worked.
            }

        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    private async Task TryToPassDateOnlyAsStructuredParamSimple()
    {
        try
        {
            var command = Connection.CreateCommand();
            command.CommandText = "[dbo].[spTestDateOnlyUdtt]";
            command.CommandTimeout = 30;
            command.CommandType = CommandType.StoredProcedure;

            //init param data
            var dates = new List<DateOnly>(new[] { new DateOnly(2023, 11, 15), new DateOnly(2022, 10, 20) });

            //populate dt parameter
            var dtDates = new DataTable();
            dtDates.Columns.Add(new DataColumn("Date", typeof(DateOnly)));

            foreach (var date in dates)
            {
                var dataRow = dtDates.NewRow();
                dataRow["Date"] = date;
                dtDates.Rows.Add(dataRow);
            }

            //pass dt parameter to procedure
            command.Parameters.Add(new SqlParameter
            {
                ParameterName = "@dates",
                SqlDbType = SqlDbType.Structured,
                TypeName = "[dbo].[udttDateOnly]",
                Value = dtDates
            });


            using (var reader = await command.ExecuteReaderAsync())
            {
                //if passes here, then it worked.
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }

    }

    #endregion
   
}

sql - udttDateOnly

  CREATE TYPE [dbo].[udttDateOnly] AS TABLE(
     [Date] DATE NULL
 )
 GO

sql - spTestDateOnlyUdtt

 CREATE OR ALTER PROC [dbo].[spTestDateOnlyUdtt]
 (
   @dates [dbo].[udttDateOnly] READONLY
 )
 AS
     SET NOCOUNT ON;

     DECLARE @context NVARCHAR(255) = '[spTestDateOnlyUdtt]'

     SELECT COUNT(*) FROM @dates;
	
 GO

sql - spTestDateOnly

CREATE OR ALTER PROC [dbo].[spTestDateOnly]
(
    @date DATE
)
AS
    SET NOCOUNT ON;

    DECLARE @context NVARCHAR(255) = '[spTestDateOnly]'

    PRINT @date
	
GO

Expected behavior

SqlParameter.Structured should pass the provided/populated udtt to the sql procedure.

Further technical details

Microsoft.Data.SqlClient version: 5.2.0-preview3.23201.1
.NET target: 8.0.100-rc.2.23502.2
SQL Server version: SQL Server 16.0.1105.1
Operating system: Windows 11 Business 23H2

@JRahnama JRahnama added the 🆕 Triage Needed For new issues, not triaged yet. label Nov 7, 2023
@JRahnama
Copy link
Contributor

JRahnama commented Nov 7, 2023

@PK-ByTE thank you for bringing this up. We will look into this and will update you.

@JRahnama JRahnama added 💡 Enhancement Issues that are feature requests for the drivers we maintain. 🙌 Up-for-Grabs Issues that are ready to be picked up for anyone interested. Please self-assign and remove the label and removed 🆕 Triage Needed For new issues, not triaged yet. labels Nov 7, 2023
@Wraith2
Copy link
Contributor

Wraith2 commented Nov 7, 2023

/cc @ErikEJ

@ErikEJ
Copy link
Contributor

ErikEJ commented Nov 8, 2023

@Wraith2 @JRahnama Yeah, diving into the 4000 line src\Microsoft.Data.SqlClient\src\Microsoft\Data\SqlClient\Server\ValueUtilsSmi.cs class 😄

ErikEJ added a commit to ErikEJ/SqlClient that referenced this issue Dec 6, 2023
…arameter

Also makes some tests run on machines in winter outside UTC time zones :-D

fixes dotnet#2209
@DavoudEshtehari DavoudEshtehari removed the 🙌 Up-for-Grabs Issues that are ready to be picked up for anyone interested. Please self-assign and remove the label label Aug 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💡 Enhancement Issues that are feature requests for the drivers we maintain.
Projects
Development

Successfully merging a pull request may close this issue.

5 participants