Checking if record exists using Dapper ORM - sql-server

I am new to Dapper, so I may be missing something obvious but I don't understand why this query is returning null even though the record exists in the table.
queryResult = db.Query<dynamic>(#"SELECT Id FROM Customer WHERE CustomerId = #CustomerId",
new { CustomerId = theCustomerId }).FirstOrDefault();
I am checking to see if the record exists and in this case it does, yet queryResult is always null. The #CustomerId parameter is a string that I am matching exactly..
If I run the SQL in SQL Server is brings up the record no problem ...
SELECT Id FROM Customer WHERE CustomerId = 'abc123'
where abc123 is the CustomerId

It returns null as you want it to do so
Following is your query getting executed, as part of Query API
"SELECT Id FROM Customer WHERE CustomerId = #CustomerId",
new { CustomerId = theCustomerId }
Now what happens when CustomerId doesn't match, it produces empty IEnumerable<dynamic>, though its a different story why dynamic, you shall use integer assuming Id is an integer
but what FirstOrDefault() does on finding an empty IEnumerable, returns null, so simply remove it do check like Any, dapper by default doesn't return null, your code is forcing it

Best way to check for existence using dapper would be:
string sql = "SELECT count(1) FROM Customer WHERE CustomerId = #CustomerId;";
bool exists = false;
using (var connection = new SqlConnection("connection string"))
{
connection.Open();
exists = connection.ExecuteScalar<bool>(sql, new { CustomerId = "abc123" });
}
As to why your specific example returns null, I suspect it's because you needed brackets around the db.Query like:
queryResult = (db.Query<dynamic>(#"SELECT Id FROM Customer WHERE CustomerId = #CustomerId",
new { CustomerId = theCustomerId })).FirstOrDefault();

Related

Create KeyValuePair<TKey, TValue> from columns in a single data row

I have the following table in Sql Server that stores the permissions the Foreign Key UserId has to the Foreign Keyed BlogId. What I would like to do is write a query with Dapper that takes each column after BlogId and returns it as a KeyValuePair<TKey, TValue>.
CREATE TABLE [dbo].[UserPermission] (
[UserPermissionId] INT IDENTITY (1, 1) NOT NULL,
[BlogId] INT NOT NULL,
[UserId] INT NOT NULL,
[CanCreateNewPosts] BIT NOT NULL,
[CanEditExistingPosts] BIT NOT NULL,
[CanDeleteExistingPosts] BIT NOT NULL,
[CanPublishDraftPosts] BIT NOT NULL,
CONSTRAINT [PK_UserPermission] PRIMARY KEY CLUSTERED ([UserPermissionId] ASC),
CONSTRAINT [FK_UserPermission_Blog] FOREIGN KEY ([BlogId]) REFERENCES [dbo].[Blog] ([BlogId]),
CONSTRAINT [FK_UserPermission_User] FOREIGN KEY ([UserId]) REFERENCES [dbo].[User] ([UserId])
);
I would like to query via Dapper like this:
using (var connection = new SqlConnection(this.connectionString))
{
string sql = "SELECT * FROM [Permission] WHERE UserId = #UserId";
await connection.OpenAsync();
IEnumerable<KeyValuePair<string, bool>> results = await connection.QueryAsync(
sql,
new { UserId = this.userId });
}
var p1 = results.First();
var p2 = results.Skip(1).First();
In the above example, I would like p1 to result in a KeyValuePair with the Key being CanCreateNewPosts and the Value being the column value, either true or false. Same applies with p2, where the Key would be CanEditExistingPosts, with it's corresponding value.
The underlying need for this is to simplify transforming the record into a list of Claims in Identity, one claim per column.
I looked at splitOn:, to try and split after the UserId column but that doesn't seem like it's what I want. It would require n-generic arguments for each column I split. Ideally I'd like to add columns to this table in the future and my security/data/servicing layer just handles turning it into a Claim - letting me just focus on the Controller Action that needs to check for the claim. Having the query and Dapper return map the column-name/values into a collection of KeyValuePairs would facilitate that need for me.
You can use the SQL UNPIVOT operation to transform columns into column values. Here's an example for your particular case:
SELECT u.BlogId, u.permission
FROM UserPermissions up
UNPIVOT
(
permission for perms in (
CanCreateNewPosts,
CanEditExistingPosts,
CanDeleteExistingPosts,
CanPublishDraftPosts
)
) u;

LINQ to loop and get the results for the same records

Lets say i have two tables with almost the same structure
TableFrom
ID bigint
Username nvarchar
Password nvarchar
Name nvarchar
TableTo
ID bigint
Username nvarchar
Password nvarchar
Now i want to generate an Insert into SQL query ( using parameters ) but only for those fields who are the same in both tables. ( id, username, password )
I thought about reading those two table structure queries into dataTable and after that loop with LINQ to get array of fields which are the same in bot tables ?
Dim dtFrom as new datatable
dim dtTo as NEW dataTable
dtTo = _LoadAvaliableToFields()
dtFrom = _loadAvailableFromFields()
How would that LINQ go ?
After that i need to add the Insert query to database using parameters. Is there any simpler way to do this ?
Using query syntax the "select" query would be very similar to a SQL query:
Dim query =
From idFrom In TableFrom _
Join idTo In TableTo _
On New With {Key .ID = idFrom.ID, Key .U = idFrom.Username, Key .P = idFrom.Password} _
Equals New With {Key .ID = idTo.ID, Key .U = idTo.Username, Key .P = idTo.Password} _
Select idFrom
To do an insert you'd need to add objects to the appropriate collections in the context, then call SaveChanges.
I would note that a direct SQL query would be more efficient:
INSERT INTO {destination}
SELECT f.ID,f.Username,f.Password
FROM TableFrom f
INNER JOIN TableTo t
ON f.ID = t.ID AND f.Username = t.Username AND f.Password = t.Password

Returning ID of new row when ID is uniqueidentifier

I have created a SQL Server table that uses uniqueidentifier as the primary key. I set the Default Value or Binding to newid(). (I would like to set the Identity Specification for this column, but that isn't supported for uniqueidentifier types.)
I'm then using ADO.NET to add a row to this table.
SqlComment command = new SqlCommand("INSERT INTO [User] (Name) VALUES (#name);
SELECT SCOPE_IDENTITY()", Connection);
command.Parameters.AddWithValue("#name", "Joe Smoe");
Guid userId = (Guid)command.ExecuteScalar();
However, the last line fails because ExecuteScaler() returns null. It appears that, since a uniqueidentifier cannot be the table's identity, SCOPE_IDENTITY() returns null (as does ##IDENTITY).
Okay, so is there another way to retrieve the newly added ID using ADO.NET?
SCOPE_IDENTITY() is only used for Identity value, for guid values you would need to use the OUTPUT clause with a table variable.
DECLARE #NewGuid TABLE(NewValue UNIQUEIDENTIFIER);
INSERT INTO [User] (Name)
OUTPUT inserted.pk_ColName INTO #NewGuid(NewValue)
VALUES (#name);
SELECT * FROM #NewGuid --<-- here you will have the new GUID Value
C# code would look something like....
string cmd = "DECLARE #NewGuid TABLE(NewValue UNIQUEIDENTIFIER);
INSERT INTO [User] (Name)
OUTPUT inserted.pk_ColName INTO #NewGuid(NewValue)
VALUES (#name);
SELECT #newID = NewValue FROM #NewGuid;"
SqlCommand command = new SqlCommand(cmd, Connection);
cmd.Parameters.AddWithValue("#name", "Joe Smoe");
cmd.Parameters.Add("#newID", SqlDbType.UniqueIdentifier).Direction = ParameterDirection.Output;
Guid userId = (Guid)cmd.ExecuteScalar();
Personally I would put the whole thing in a stored procedure.
Scope_Identity() focuses on an IDENTITY field, so it will never yield anything. You need to output from INSERTED instead. Even though this page is not focused on your particular problem, it should give you some clues:
Return ID on INSERT?
My normal direction is a stored procedure, but you can chain commands, as you have done. The stored procedure makes things a bit easier, as you can create an output parameter for the procedure, but outputting a value works fine.
EDITED to show specific example:
Assume the following table:
CREATE TABLE [dbo].[MyTable]
(
[Id] [uniqueidentifier] PRIMARY KEY NOT NULL DEFAULT NEWID(),
[Name] [varchar](50) NOT NULL,
)
The following program will output the new GUID created from NewID():
class Program
{
static void Main(string[] args)
{
var connString = ConfigurationManager.ConnectionStrings["testDB"].ToString();
var cmdString = "INSERT INTO MyTable (Name) OUTPUT Inserted.Id VALUES ('Name')";
var connection = new SqlConnection(connString);
var command = new SqlCommand(cmdString, connection);
Guid outputValue;
try
{
connection.Open();
//Convert to Guid here instead
Console.WriteLine(command.ExecuteScalar().ToString());
}
finally
{
connection.Dispose();
}
Console.Read();
}
}

SQL Server isnull is not working with another expression?

I'm trying to make an expression in SQL Server, that will check if certain column is null, and if it is null, set a new GUID number..
This is my code :
select
isnull((select Guid
from therapists
where username = 'ido' and password = 'ido'),
(update therapists
set guid = NEWID()
where username = 'ido' and password = 'ido'))
You can try this:
UPDATE therapists SET guid = NEWID()
WHERE username = 'ido'
AND password = 'ido'
AND guid IS NULL;

Simple While loop database search table

first of all: Thanks for all the great help I already received through finding answers to questions others posted.
I have a small and easy question for you:
I'm trying to randomly generate a number, but if it exists in the database table, it should keep generating a new numbers until it finds a unique number.
Help would be much appreciated!
$klantnr = rand(1,9);
$kn = mysql_num_rows(mysql_query('select username from users where id="'.$klantnr.'"'));
while($kn!=0){
$klantnr = rand(1,9);
}
echo $klantnr;
Create table with:
id integer primary key auto_increment
insert into users (id, username) values (NULL, 'name')
insert into users (username) values ('name')
MySQL will generate unique id for you
=== update
create table random_id (
id integer,
used tinyint,
primary key(id),
key idx_used(used)
);
for (0..9999) {
rand_id = get_random_id();
insert into random_id (id, used) values (rand_id, 0);
}
When need a random id, just fetch one from random_id table:
rand_id = select id from random_id where used = 0;
update random_id set used = 1 where id = :rand_id
use rand_id
Really it's pre generated random id, if you guarantee the users table's id only from random table, you doesn't need dealing with conflict ids :)

Resources