Related
I am trying to pass my DataTable to a stored procedure. The DataTable holds the contents of an Excel sheet. The Excel sheet has two empty columns, five with text, and five with decimal numbers.
The empty columns are OppdragsMVAkode and OppdragsgebyrMVAkode.
If I run my application, I get this exception:
System.ArgumentException: Input string was not in a correct format. Couldn't store <> in OppdragsMVAkode Column. Expected type is Decimal.
If I add a temporary number, I get this exception:
System.Data.SqlClient.SqlException: Error converting data type nvarchar to numeric.
I don't get why it's reading it as a string.
My stored procedure (spGetTrips):
ALTER PROCEDURE [dbo].[spGetTrips]
#trips udtTripsPerMonth readonly
AS
BEGIN
INSERT INTO tblTripsPerMonth
SELECT
[KjøretøyID],
SUBSTRING([År], 7, 4),
SUBSTRING([Måned], 4, 2),
[Betaling (brutto)],
[Betaling (netto)],
[Bestillingsgebyr (netto)],
[Betalingsgebyr (netto)],
[OppdragsMVAkode],
CONCAT(LøyvehaverFakturaID, + 'UF-' + SUBSTRING([År], 9, 2) + SUBSTRING([Måned], 4, 2)),
[Oppdragsgebyr (netto)],
[OppdragsgebyrMVAkode],
CONCAT([RidelRegionFakturaID], + 'UF-' + SUBSTRING([År], 9, 2) + SUBSTRING([Måned], 4, 2))
FROM #trips
UPDATE tblTripsPerMonth
SET [OppdragsMVAkode] = (
SELECT [ID]
FROM [tblMVAkoder]
WHERE [ID] = 'MVAkode2'
);
UPDATE tblTripsPerMonth
SET [OppdragsgebyrMVAkode] = (
SELECT [ID]
FROM [tblMVAkoder]
WHERE [ID] = 'MVAkode5'
);
END
As you can see above, I am setting the value of the two empty columns with UPDATE clauses in the Stored Procedure. Whether they are empty in the Excel sheet, or with some preliminary value, and then to be overridden, I care not - I just want it to work.
Here's my User-Defined Table Type (udtTripsPerMonth):
CREATE TYPE [dbo].[udtTripsPerMonth] AS TABLE(
[KjøretøyID] [nvarchar](50) NULL,
[År] [nvarchar](50) NULL,
[Måned] [nvarchar](50) NULL,
[Betaling (brutto)] [decimal](10, 2) NULL,
[Betaling (netto)] [decimal](10, 2) NULL,
[Bestillingsgebyr (netto)] [decimal](10, 2) NULL,
[Betalingsgebyr (netto)] [decimal](10, 2) NULL,
[OppdragsMVAkode] [decimal](10, 2) NULL,
[LøyvehaverFakturaID] [nvarchar](50) NULL,
[Oppdragsgebyr (netto)] [decimal](10, 2) NULL,
[OppdragsgebyrMVAkode] [decimal](10, 2) NULL,
[RidelRegionFakturaID] [nvarchar](50) NULL
)
GO
And my table (tblTripsPerMonth):
CREATE TABLE [dbo].[tblTripsPerMonth](
[ID] [int] IDENTITY(1,1) NOT NULL,
[KjøretøyID] [nvarchar](50) NULL,
[År] [nvarchar](50) NULL,
[Måned] [nvarchar](50) NULL,
[Betaling (brutto)] [decimal](10, 2) NULL,
[Betaling (netto)] [decimal](10, 2) NULL,
[Bestillingsgebyr (netto)] [decimal](10, 2) NULL,
[Betalingsgebyr (netto)] [decimal](10, 2) NULL,
[OppdragsMVAkode] [decimal](10, 2) NULL,
[LøyvehaverFakturaID] [nvarchar](50) NULL,
[Oppdragsgebyr (netto)] [decimal](10, 2) NULL,
[OppdragsgebyrMVAkode] [decimal](10, 2) NULL,
[RidelRegionFakturaID] [nvarchar](50) NULL,
PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
The other table I reference in the UPDATE clauses (tblMVAkoder):
CREATE TABLE [dbo].[tblMVAkoder](
[ID] [nvarchar](50) NOT NULL,
[Startdato] [date] NULL,
[Sluttdato] [date] NULL,
[MVAsats] [decimal](10, 2) NULL,
PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
GO
Here's my C# code (Excel to DataTable):
private void btnExport_Click(object sender, RoutedEventArgs e) {
OpenFileDialog of = new();
of.Filter = "Excel Files | *.xlsx;";
of.Title = "Importer Excel fil.";
if (of.ShowDialog() == true) {
dgPaidTrip.ItemsSource = ImportExceltoDataTable(of.FileName).DefaultView;
btnClearForm.IsEnabled = true;
}
using (SqlConnection con = new(ConnectionString.connectionString))
using (var cmd = new SqlCommand("spGetTrips", con) { CommandType = CommandType.StoredProcedure }) {
con.Open();
DataTable dt = ImportExceltoDataTable(of.FileName);
cmd.Parameters.Add(new SqlParameter("#trips", dt));
cmd.ExecuteNonQuery();
}
}
public static DataTable ImportExceltoDataTable(string filePath) {
using (XLWorkbook wb = new(filePath)) {
IXLWorksheet ws = wb.Worksheet(1);
int tl_Row = ws.FirstCellUsed().Address.RowNumber;
int tl_Col = ws.FirstCellUsed().Address.ColumnNumber;
int br_Row = ws.LastCellUsed().Address.RowNumber;
int br_Col = ws.LastCellUsed().Address.ColumnNumber;
DataTable dt = new();
dt.Columns.Add("KjøretøyID", typeof(string));
dt.Columns.Add("År", typeof(string));
dt.Columns.Add("Måned", typeof(string));
dt.Columns.Add("Betaling (brutto)", typeof(decimal));
dt.Columns.Add("Betaling (netto)", typeof(decimal));
dt.Columns.Add("Bestillingsgebyr (netto)", typeof(decimal));
dt.Columns.Add("Betalingsgebyr (netto)", typeof(decimal));
dt.Columns.Add("OppdragsMVAkode", typeof(decimal));
dt.Columns.Add("LøyvehaverFakturaID", typeof(string));
dt.Columns.Add("Oppdragsgebyr (netto)", typeof(decimal));
dt.Columns.Add("OppdragsgebyrMVAkode", typeof(decimal));
dt.Columns.Add("RidelRegionFakturaID", typeof(string));
IXLRow currentRow;
for (int dtRow = 0; dtRow < br_Row - tl_Row; dtRow++) {
currentRow = ws.Row(tl_Row + dtRow + 1);
dt.Rows.Add();
for (int dtCol = 0; dtCol < br_Col - tl_Col + 1; dtCol++) {
dt.Rows[dtRow][dtCol] = currentRow.Cell(tl_Col + dtCol).Value;
}
}
return dt;
}
}
As far as I can see, all my column types match, as well as their order.
I changed all my types to nvarchar, and the code "works".
But someone smarter than me told me it was not a good idea to fake the column types.
What am I missing?
To pass a null value, you need to set the column value as DBNull.Value. You can set DBNull like this
dt.Rows[dtRow][dtCol] = currentRow.Cell(tl_Col + dtCol).Value ?? (object)DBNull.Value;
You must also set SqlDBType TypeName and Direction properties
cmd.Parameters.Add(
new SqlParameter("#trips", SqlDBType.Structured)
{
TypeName = "dbo.udtTripsPerMonth",
Direction = ParameterDirection.Input,
Value = dt
});
I am trying to write a C# program (.Net core 2.1) to read all the check constraints for a given table from ms sql server database. I am using sys.check_constraints table to get this information, when I tried to read this using ado.net datareader the column 'definition' from this table is always coming as empty though it has value.
SQL Script (DDL, Stored Proc to Get CheckConstraints, Exec state of Stored Proc)
GO
/****** Object: Table [dbo].[Customer] Script Date: 7/10/2019 3:24:22 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Customer](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[CompanyId] [smallint] NOT NULL,
[Prefix] [varchar](4) NOT NULL,
[FirstName] [varchar](50) NOT NULL,
[LastName] [varchar](50) NOT NULL,
[MiddleName] [varchar](50) NULL,
[Suffix] [varchar](4) NULL,
[NickName] [varchar](10) NULL,
[ProfilePictureName] [varchar](50) NULL,
[Company] [varchar](100) NULL,
[DateOfBirth] [date] NOT NULL,
[DateOfDeath] [date] NULL,
[Gender] [char](1) NOT NULL,
[Type] [varchar](10) NOT NULL,
[IsActive] [char](1) NULL,
[CreatedBy] [varchar](50) NOT NULL,
[CreatedOn] [datetime2](7) NOT NULL,
[UpdatedBy] [varchar](50) NULL,
[UpdatedOn] [datetime2](7) NULL,
[Process] [varchar](100) NULL,
[MessageId] [varchar](50) NOT NULL,
[SysStartDate] [datetime2](2) GENERATED ALWAYS AS ROW START NOT NULL,
[SysEndDate] [datetime2](2) GENERATED ALWAYS AS ROW END NOT NULL,
CONSTRAINT [PK_CUSTOMER] PRIMARY KEY CLUSTERED
(
[Id] ASC,
[CompanyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
PERIOD FOR SYSTEM_TIME ([SysStartDate], [SysEndDate])
) ON [PRIMARY]
WITH
(
SYSTEM_VERSIONING = ON ( HISTORY_TABLE = [dbo].[MSSQL_TemporalHistoryFor_601769201] )
)
GO
ALTER TABLE [dbo].[Customer] ADD DEFAULT ('Y') FOR [IsActive]
GO
ALTER TABLE [dbo].[Customer] WITH CHECK ADD CONSTRAINT [CUSTOMER_PREFIX_CHECK] CHECK (([Prefix]='Dr' OR [Prefix]='Miss' OR [Prefix]='Ms' OR [Prefix]='Mrs' OR [Prefix]='Mr'))
GO
ALTER TABLE [dbo].[Customer] CHECK CONSTRAINT [CUSTOMER_PREFIX_CHECK]
GO
ALTER TABLE [dbo].[Customer] WITH CHECK ADD CONSTRAINT [CUSTOMER_SUFFIX_CHECK] CHECK (([Suffix]='RN' OR [Suffix]='MD' OR [Suffix]='ESQ' OR [Suffix]='DO' OR [Suffix]='DDS' OR [Suffix]='DDM' OR [Suffix]='III' OR [Suffix]='II' OR [Suffix]='I' OR [Suffix]='Sr' OR [Suffix]='Jr'))
GO
ALTER TABLE [dbo].[Customer] CHECK CONSTRAINT [CUSTOMER_SUFFIX_CHECK]
GO
ALTER TABLE [dbo].[Customer] WITH CHECK ADD CONSTRAINT [CUSTOMER_TYPE_CHECK] CHECK (([Type]='Customer' OR [Type]='VENDOR' OR [Type]='INSIDER' OR [Type]='ANALYST' OR [Type]='INVESTOR'))
GO
ALTER TABLE [dbo].[Customer] CHECK CONSTRAINT [CUSTOMER_TYPE_CHECK]
GO
CREATE PROCEDURE [dbo].[GetCheckConstraints_Dup](#tableName as varchar(200))
AS
BEGIN
select
col.[name] as column_name,
con.[definition] As [constraint_value]
from sys.check_constraints con
left outer join sys.objects t
on con.parent_object_id = t.object_id
left outer join sys.all_columns col
on con.parent_column_id = col.column_id
and con.parent_object_id = col.object_id
where t.[name]=#tableName and con.is_disabled=0
order by con.name;
End;
GO
exec GetCheckConstraints_Dup 'Customer'
SQL Server Result
C#
public static List<Constraints> GetConstraints(string tableName,string connectionString)
{
var constraints = new List<Constraints>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
//SqlDataReader
connection.Open();
SqlCommand cmd = new SqlCommand("DBO.GetCheckConstraints_Dup", connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#tableName", SqlDbType.VarChar).Value = tableName;
using (SqlDataReader dataReader = cmd.ExecuteReader())
{
while (dataReader.Read())
{
constraints.Add(new Constraints() { FieldName = dataReader["column_name"].ToString(), Constraint = ConstraintType.Check, ConstraintValue = dataReader["constraint_value"].ToString() });
}
}
}
return constraints;
}
No repro for me. Does this repro?
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApp18
{
class Program
{
static string ddl = #"
GO
--if exists (select * from sys.tables where name = 'Customer')
-- begin
-- ALTER TABLE [dbo].[Customer] SET ( SYSTEM_VERSIONING = OFF)
-- DROP TABLE [dbo].[Customer]
-- DROP TABLE [dbo].[MSSQL_TemporalHistoryFor_601769201]
--end
go
/****** Object: Table [dbo].[Customer] Script Date: 7/10/2019 3:24:22 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TABLE [dbo].[Customer](
[Id] [bigint] IDENTITY(1,1) NOT NULL,
[CompanyId] [smallint] NOT NULL,
[Prefix] [varchar](4) NOT NULL,
[FirstName] [varchar](50) NOT NULL,
[LastName] [varchar](50) NOT NULL,
[MiddleName] [varchar](50) NULL,
[Suffix] [varchar](4) NULL,
[NickName] [varchar](10) NULL,
[ProfilePictureName] [varchar](50) NULL,
[Company] [varchar](100) NULL,
[DateOfBirth] [date] NOT NULL,
[DateOfDeath] [date] NULL,
[Gender] [char](1) NOT NULL,
[Type] [varchar](10) NOT NULL,
[IsActive] [char](1) NULL,
[CreatedBy] [varchar](50) NOT NULL,
[CreatedOn] [datetime2](7) NOT NULL,
[UpdatedBy] [varchar](50) NULL,
[UpdatedOn] [datetime2](7) NULL,
[Process] [varchar](100) NULL,
[MessageId] [varchar](50) NOT NULL,
[SysStartDate] [datetime2](2) GENERATED ALWAYS AS ROW START NOT NULL,
[SysEndDate] [datetime2](2) GENERATED ALWAYS AS ROW END NOT NULL,
CONSTRAINT [PK_CUSTOMER] PRIMARY KEY CLUSTERED
(
[Id] ASC,
[CompanyId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
PERIOD FOR SYSTEM_TIME ([SysStartDate], [SysEndDate])
) ON [PRIMARY]
WITH
(
SYSTEM_VERSIONING = ON ( HISTORY_TABLE = [dbo].[MSSQL_TemporalHistoryFor_601769201] )
)
GO
ALTER TABLE [dbo].[Customer] ADD DEFAULT ('Y') FOR [IsActive]
GO
ALTER TABLE [dbo].[Customer] WITH CHECK ADD CONSTRAINT [CUSTOMER_PREFIX_CHECK] CHECK (([Prefix]='Dr' OR [Prefix]='Miss' OR [Prefix]='Ms' OR [Prefix]='Mrs' OR [Prefix]='Mr'))
GO
ALTER TABLE [dbo].[Customer] CHECK CONSTRAINT [CUSTOMER_PREFIX_CHECK]
GO
ALTER TABLE [dbo].[Customer] WITH CHECK ADD CONSTRAINT [CUSTOMER_SUFFIX_CHECK] CHECK (([Suffix]='RN' OR [Suffix]='MD' OR [Suffix]='ESQ' OR [Suffix]='DO' OR [Suffix]='DDS' OR [Suffix]='DDM' OR [Suffix]='III' OR [Suffix]='II' OR [Suffix]='I' OR [Suffix]='Sr' OR [Suffix]='Jr'))
GO
ALTER TABLE [dbo].[Customer] CHECK CONSTRAINT [CUSTOMER_SUFFIX_CHECK]
GO
ALTER TABLE [dbo].[Customer] WITH CHECK ADD CONSTRAINT [CUSTOMER_TYPE_CHECK] CHECK (([Type]='Customer' OR [Type]='VENDOR' OR [Type]='INSIDER' OR [Type]='ANALYST' OR [Type]='INVESTOR'))
GO
ALTER TABLE [dbo].[Customer] CHECK CONSTRAINT [CUSTOMER_TYPE_CHECK]
GO
CREATE OR ALTER PROCEDURE [dbo].[GetCheckConstraints_Dup](#tableName as varchar(200))
AS
BEGIN
select
col.[name] as column_name,
con.[definition] As [constraint_value]
from sys.check_constraints con
left outer join sys.objects t
on con.parent_object_id = t.object_id
left outer join sys.all_columns col
on con.parent_column_id = col.column_id
and con.parent_object_id = col.object_id
where t.[name]=#tableName and con.is_disabled=0
order by con.name;
End;
GO
";
static IEnumerable<string> GetBatches(string script)
{
var rdr = new System.IO.StringReader(script);
var sb = new StringBuilder();
while (true)
{
var l = rdr.ReadLine()?.Trim();
if (l == null)
{
var batch = sb.ToString().Trim();
if (batch.Length > 0)
yield return sb.ToString();
break;
}
else if (l.Equals( "GO", StringComparison.OrdinalIgnoreCase))
{
var batch = sb.ToString().Trim();
if (batch.Length > 0)
yield return sb.ToString();
sb.Clear();
}
else
{
sb.AppendLine(l.Trim());
}
}
}
static void Main(string[] args)
{
var constr = "Server=localhost;database=tempdb;integrated security=true";
using (var con = new SqlConnection(constr))
{
con.Open();
foreach (var batch in GetBatches(ddl))
{
var cmd = con.CreateCommand();
cmd.CommandText = batch;
cmd.ExecuteNonQuery();
}
var constraints = GetConstraints("Customer", constr);
foreach (var constraint in constraints)
{
Console.WriteLine($"{constraint.FieldName} {constraint.ConstraintValue}");
}
}
Console.WriteLine("Hit any key to exit");
Console.ReadKey();
}
public static List<Constraints> GetConstraints(string tableName, string connectionString)
{
var constraints = new List<Constraints>();
using (SqlConnection connection = new SqlConnection(connectionString))
{
//SqlDataReader
connection.Open();
SqlCommand cmd = new SqlCommand("DBO.GetCheckConstraints_Dup", connection);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("#tableName", SqlDbType.VarChar).Value = tableName;
using (SqlDataReader dataReader = cmd.ExecuteReader())
{
while (dataReader.Read())
{
constraints.Add(new Constraints() { FieldName = dataReader["column_name"].ToString(), Constraint = "Check", ConstraintValue = dataReader["constraint_value"].ToString() });
}
}
}
return constraints;
}
public class Constraints
{
public string FieldName { get; internal set; }
public string Constraint { get; internal set; }
public string ConstraintValue { get; internal set; }
}
}
}
I have a table:
CREATE TABLE [dbo].[DeliveryData](
[DeliveryId] [int] IDENTITY(1,1) NOT NULL,
...
CONSTRAINT [PK_DeliveryData] PRIMARY KEY CLUSTERED
(
[DeliveryId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
And code:
public void GetPrimaryKeyColumns(SqlConnection conn) {
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "select * from [dbo].[DeliveryData]";
SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SchemaOnly);
DataTable schema = reader.GetSchemaTable();
DataColumn[] columns = schema.PrimaryKey;
...
}
cmd, reader, and schema all look good, but columns ends up a zero length array. Shouldn't it contain "DeliveryId"? How can I get the primary column "DeliveryId"?
Thanks for the help!
Blake
MSSQL doesn't return correct primary key information in all cases using GetSchemaTable. (Not too surprising. For example, almost all DB vendors support ODBC better than MS.) The following query, however, does work:
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE as kcu
ON kcu.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG
AND kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
AND kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
AND kcu.TABLE_CATALOG = tc.TABLE_CATALOG
AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA
AND kcu.TABLE_NAME = tc.TABLE_NAME
WHERE tc.CONSTRAINT_TYPE ='PRIMARY KEY'
AND tc.TABLE_SCHEMA = 'dbo'
AND tc.TABLE_NAME = 'DeliveryData'
ORDER BY ORDINAL_POSITION;
The schema table is not the DeliveryData table. You must inspect the schema table where the IsKey column is true and then grab the ColumnName field. You can then use that find the real column on a regular data table.
Update
GetSchemaTable() returns a data table of metadata information which you can see in the documentation: https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqldatareader.getschematable(v=vs.110).aspx
You end up with as many rows in the returned DataTable as you would have columns in the query if you were to run the query. Here is a partial screenshot of the schema table I get from a test table in my database. Notice every column is now a row, and the IsKey field will tell you if the column is a key column:
If you want to use the PrimaryKey property on a DataTable do not use GetSchemaTable(), just use a SqlDataAdapter to fill a regular DataTable.
Update 2
use CommandBehavior.KeyInfo instead of CommandBehavior.SchemaOnly
Using SMO
using Microsoft.SqlServer.Management.Smo;
....
Server svr = new Server("Your Server Name");
Database db = svr.Databases["Your Database Name"];
Table tbl = db.Tables["DeliveryData"];
foreach (Column c in tbl.Columns)
{
bool isAKeyColumn = c.InPrimaryKey
}
This is a complete solution:
public List<string> GetPrimaryKeyColumns(DbConnection conn, string schema, string table) {
DbCommand cmd = conn.CreateCommand();
DbParameter p = cmd.CreateParameter();
p.ParameterName = "#schema";
p.Value = schema;
p.DbType = DbType.String;
p.Direction = ParameterDirection.Input;
cmd.Parameters.Add(p);
p = cmd.CreateParameter();
p.ParameterName = "#table";
p.Value = table;
p.DbType = DbType.String;
p.Direction = ParameterDirection.Input;
cmd.Parameters.Add(p);
cmd.CommandText = #"SELECT kcu.COLUMN_NAME
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS as tc
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE as kcu
ON kcu.CONSTRAINT_CATALOG = tc.CONSTRAINT_CATALOG
AND kcu.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
AND kcu.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
-- AND kcu.TABLE_CATALOG = tc.TABLE_CATALOG doesn't work on MySQL
AND kcu.TABLE_SCHEMA = tc.TABLE_SCHEMA
AND kcu.TABLE_NAME = tc.TABLE_NAME
WHERE tc.CONSTRAINT_TYPE ='PRIMARY KEY'
AND tc.TABLE_SCHEMA = #schema
AND tc.TABLE_NAME = #table
ORDER BY ORDINAL_POSITION";
DbDataReader reader = cmd.ExecuteReader(CommandBehavior.KeyInfo);
List<string> res = new List<string>();
while (reader.Read()) {
var str = reader[0];
if (str != System.DBNull.Value)
res.Add((string) str);
}
reader.Dispose();
cmd.Dispose();
return res;
}
I have researched this and apologize if this is duplicate, but I cant seem to find the correct answer, and I learn so much from this site.
I have 3 tables:
CREATE TABLE [Reporting].[ReportingCompanies](
[ID] [int] IDENTITY(1,1) NOT NULL,
[EINC] [int] NOT NULL,
[CompanyId] [varchar](4) NOT NULL,
[CompanyName] [varchar](50) NOT NULL,
[LastClosedWeek] [datetime] NOT NULL,
[PriorWeekSales] [decimal](14, 4) NULL,
[PriorWeek] [datetime] NULL,
[CurrentWeek] [datetime] NULL,
[LastWeekSales] [decimal](14, 4) NULL,
[AgingBalance] [decimal](14, 4) NULL,
[DataAsOf] [datetime] NULL,
[Tier] [int] NULL,
[CurrentWeeklyAverage] [decimal](14, 4) NULL,
[AvgAged] [decimal](14, 4) NULL,
[hasSpread] [bit] NULL,
[DSO] [int] NULL,
[isFamily] [bit] NULL,
[ImportStatus] [bit] NULL,
[ClientStatus] [varchar](50) NULL,
CONSTRAINT [PK_ReportingCompanies] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [Reporting].[AllowedCompanies](
[ID] [int] IDENTITY(1,1) NOT NULL,
[CustomUserProfileUserId] [uniqueidentifier] NOT NULL,
[CustomUserProfileID] [int] NOT NULL,
[ReportingCompanyID] [int] NOT NULL,
CONSTRAINT [PK_AllowedCompanies] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [Reporting].[CustomUserProfiles](
[ID] [int] IDENTITY(1,1) NOT NULL,
[ApplicationId] [uniqueidentifier] NOT NULL,
[UserId] [uniqueidentifier] NOT NULL,
[UserName] [nvarchar](256) NOT NULL,
[LoweredUserName] [nvarchar](256) NOT NULL,
[MobileAlias] [nvarchar](16) NULL,
[IsAnonymous] [bit] NOT NULL,
[LastActivityDate] [datetime] NOT NULL,
[ImportStatus] [bit] NULL,
CONSTRAINT [PK_CustomUserProfiles] PRIMARY KEY CLUSTERED
(
[UserId] ASC,
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
I now need to add a 4th table using a left outer join, to only get a default value of 0 for the VisitCount column if no records exist.
CREATE TABLE [PayJot].[FavoriteClients](
[FavRowID] [int] IDENTITY(1,1) NOT NULL,
[Userid] [uniqueidentifier] NOT NULL,
[CompanyId] [int] NOT NULL,
[VisitCount] [int] NOT NULL,
CONSTRAINT [PK_FavoriteClients] PRIMARY KEY CLUSTERED
(
[FavRowID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Here is my latest attempt which returns the error "The entity or complex type 'DALModel.FavoriteClient' cannot be constructed in a LINQ to Entities query" but that's exactly what intellisense seems to be asking for (?)
var userName = HttpContext.Current.User.Identity.Name;
var q = from c in db.ReportingCompanies1
join a in db.AllowedCompanies on new { ID = (int)c.ID } equals new { ID = a.ReportingCompanyID }
join p in db.CustomUserProfiles on new { CustomUserProfileID = a.CustomUserProfileID } equals new { CustomUserProfileID = p.ID }
join f in db.FavoriteClients on new { A = c.ID, B = p.UserId } equals new { A = f.CompanyId, B = f.Userid } into fvc
from userfavs in fvc.DefaultIfEmpty(new FavoriteClient { CompanyId = c.ID, Userid = p.UserId , VisitCount = 0 })
where
p.UserName == userName
orderby c.CompanyName
select new Clients()
{
ID = c.ID,
CompanyId = c.CompanyId,
CompanyName = c.CompanyName,
visitCount = userfavs.VisitCount
};
ObservableCollection<Clients> clientList = new ObservableCollection<Clients>(q.ToList());
I am fairly new to Linq and while all the examples I have read make sense as explained, they fail miserably in implementation. Please advise if you can and thanx in advance.
I just got it working:
var q = from p in db.CustomUserProfiles
join a in db.AllowedCompanies on new { ID = p.ID } equals new { ID = a.CustomUserProfileID }
join c in db.ReportingCompanies1 on new { ReportingCompanyID = (int)(int)a.ReportingCompanyID } equals new { ReportingCompanyID = c.ID }
join f in db.FavoriteClients
on new { a.CustomUserProfileUserId, ReportingCompanyID = a.ReportingCompanyID }
equals new { CustomUserProfileUserId = (Guid)f.Userid, ReportingCompanyID = f.CompanyId } into FavoriteClients_join
from FavoriteClients in FavoriteClients_join.DefaultIfEmpty()
where
p.UserName == userName
orderby
FavoriteClients.VisitCount descending,
c.CompanyName
select new Clients()
{
ID = c.ID,
CompanyId = c.CompanyId,
CompanyName = c.CompanyName,
visitCount = ((Int32?)FavoriteClients.VisitCount ?? (Int32)0)
};
How can I pass a DataTable from C# to SQL Server 2008?
Exception:
The table type parameter '#CurrentTableInitial' must have a valid type
name.
Table structure:
CREATE TABLE [dbo].[RegisterChoiceUserInitial](
[RegisterChoiceUserInitialID] [int] IDENTITY(1,1) NOT NULL,
[UserId] [uniqueidentifier] NOT NULL,
[RegisterChoiceUserInitialJob] [nvarchar](50) NULL,
[RegisterChoiceUserInitialOrganization] [nvarchar](50) NULL,
[RegisterChoiceUserInitialUnit] [nvarchar](50) NULL,
[RegisterChoiceUserInitialMembershipType] [nvarchar](50) NULL,
[RegisterChoiceUserInitialStart] [nvarchar](10) NULL,
[RegisterChoiceUserInitialEnd] [nvarchar](10) NULL,
CONSTRAINT [PK_RegisterChoiceUserInitial] PRIMARY KEY CLUSTERED
(
[RegisterChoiceUserInitialID] ASC
)
User-defined type:
CREATE TYPE [dbo].[TableTypeInitial] AS TABLE(
[ID] [int] NULL,
[InitialJob] [nvarchar](50) NULL,
[InitialOrganization] [nvarchar](50) NULL,
[InitialUnit] [nvarchar](50) NULL,
[InitialMembershipType] [nvarchar](50) NULL,
[InitialMembershipStart] [nvarchar](10) NULL,
[InitialMembershipEnd] [nvarchar](10) NULL
)
Stored procedure:
create PROCEDURE [dbo].[FinishRegisterChoiceUserInitial]
( #UserId uniqueidentifier,
#TableVariable TableTypeInitial READONLY)
AS
BEGIN
INSERT INTO [Election].[dbo].[RegisterChoiceUserInitial]
([UserId]
,[RegisterChoiceUserInitialJob]
,[RegisterChoiceUserInitialOrganization]
,[RegisterChoiceUserInitialUnit]
,[RegisterChoiceUserInitialMembershipType]
,[RegisterChoiceUserInitialStart]
,[RegisterChoiceUserInitialEnd])
SELECT
#UserId AS UserId
,InitialJob
,InitialOrganization
,InitialUnit
,InitialMembershipType
,InitialMembershipStart
,InitialMembershipEnd
FROM
#TableVariable
END
DataTable:
DataTableInitial.Columns.Add(new DataColumn("ID", typeof(int)));
DataTableInitial.Columns.Add(new DataColumn("InitialJob", typeof(String)));
DataTableInitial.Columns.Add(new DataColumn("InitialOrganization", typeof(String)));
DataTableInitial.Columns.Add(new DataColumn("InitialUnit", typeof(String)));
DataTableInitial.Columns.Add(new DataColumn("InitialMembershipType", typeof(String)));
DataTableInitial.Columns.Add(new DataColumn("InitialMembershipStart", typeof(String)));
DataTableInitial.Columns.Add(new DataColumn("InitialMembershipEnd", typeof(String)));
cmd.CommandText = "EXEC FinishRegisterChoiceUserInitial #UserId, #CurrentTableInitial ";
cmd.Parameters.AddWithValue("#UserId",user.ProviderUserKey);
DataTable TableInitial=(DataTable)ViewState["CurrentTableInitial"];
SqlParameter a = cmd.Parameters.AddWithValue("#CurrentTableInitial", TableInitial);
a.SqlDbType = SqlDbType.Structured;
cmd.ExecuteNonQuery();
You were missing a.TypeName = "dbo.TableTypeInitial";
Put this statement before "a.SqlDbType = SqlDbType.Structured;"
Use
cmd.CommandText = "EXEC FinishRegisterChoiceUserInitial #UserId, #TableTypeInitial ";
instead of
cmd.CommandText = "EXEC FinishRegisterChoiceUserInitial #UserId, #CurrentTableInitial ";
Sql Server Scripts :
CREATE TABLE [Target]
(
[ID] [int] NOT NULL PRIMARY KEY IDENTITY,
[FirstName] [varchar](100)NOT NULL,
[LastName] [varchar](100)NOT NULL,
[Email] [varchar](200) NOT NULL
)
CREATE TYPE [TargetUDT] AS TABLE
(
[FirstName] [varchar](100)NOT NULL,
[LastName] [varchar](100)NOT NULL,
[Email] [varchar](200) NOT NULL
)
CREATE PROCEDURE AddToTarget(#TargetUDT TargetUDT READONLY)
AS
BEGIN
INSERT INTO [Target]
SELECT * FROM #TargetUDT
END
Sample Code :
public static void StartProcess()
{
//Create a local data table to hold customer records
DataTable dtCustomers = new DataTable("Customers");
DataColumn dcFirstName = new DataColumn("FirstName", typeof(string));
DataColumn dcLastName = new DataColumn("LastName", typeof(string));
DataColumn dcEmail = new DataColumn("Email", typeof(string));
dtCustomers.Columns.Add(dcFirstName);
dtCustomers.Columns.Add(dcLastName);
dtCustomers.Columns.Add(dcEmail);
//Add customer 1
DataRow drCustomer = dtCustomers.NewRow();
drCustomer["FirstName"] = "AAA";
drCustomer["LastName"] = "XYZ";
drCustomer["Email"] = "aaa#test.com";
dtCustomers.Rows.Add(drCustomer);
//Add customer 2
drCustomer = dtCustomers.NewRow();
drCustomer["FirstName"] = "BBB";
drCustomer["LastName"] = "XYZ";
drCustomer["Email"] = "bbb#test.com";
dtCustomers.Rows.Add(drCustomer);
//Add customer 3
drCustomer = dtCustomers.NewRow();
drCustomer["FirstName"] = "CCC";
drCustomer["LastName"] = "XYZ";
drCustomer["Email"] = "ccc#test.com";
dtCustomers.Rows.Add(drCustomer);
//Create Connection object to connect to server/database
SqlConnection conn = new SqlConnection(ConStr);
conn.Open();
//Create a command object that calls the stored procedure
SqlCommand cmdCustomer = new SqlCommand("AddToTarget", conn);
cmdCustomer.CommandType = CommandType.StoredProcedure;
//Create a parameter using the new SQL DB type viz. Structured to pass as table value parameter
SqlParameter paramCustomer = cmdCustomer.Parameters.Add("#TargetUDT", SqlDbType.Structured);
paramCustomer.Value = dtCustomers;
//Execute the query
cmdCustomer.ExecuteNonQuery();
}