I may have a slightly naive question, but I have never worked with databases before. I am a .NET engineer and I use Dapper to access the SQL Server database.
The situation is the following: I have a denormalized table for persisting several types of entities. Each has a composite key (type, id, owner_id) and each row of the key is of string type (but it's not important). And, let's say, I'm writing to the database many interests for different users (Bulk post). In order for them to not repeat, I need to make a query and determine which are already present in the database.
So, I have this code in my InterestService
class:
private IEnumerable<Interest> GetAlreadyExistingInterestsFor(IEnumerable<Interest> interestsForCreating) =>
_interestRepository.GetInterests(interestsForCreating.Select(interest => interest.Id).ToList(),
interestsForCreating.Select(interest => interest.UserId).ToList());
After that I have some logic and so on. It's not important.
InterestRepository
method GetInterests
looks like this:
public GetInterests(IList<string> interestIds, IList<string> userIds)
{
var query = @"SELECT type, id, owner_id
FROM entities
WHERE type = 'interest'
AND id IN @InterestIds
AND owner_id IN @UserIds";
return _dbContext.ExecuteQuery(query, new { InterestIds = interestIds, UserIds = userIds });
}
The code may have mistakes because right now I don't have an ability to access a working environment but I think the idea is clear. So, the question is whether this is the best approach to making a query. And if there is a better, then what is it.
Essentially you can simply do exactly what was done in this post, but with two sets instead of 1 for the table valued parameter. Using Dapper, how do I pass in the values for a sql type as param?
It uses a stored procedure and a sql table valued parameter.
If stored procedure
is not an option then you can use one of following methods.
interestIds
and userIds
into stringsstring interests = "(1, 2, 3, 4)"
if lists contains numbers only or ('a1', 'b1', 'c2')
if they are strings. Then just inline them into your query
var query = @"SELECT type, id, owner_id
FROM entities
WHERE type = 'interest'
AND id IN "+ interests
+ " AND owner_id IN " + users;
This method is considered as bad practice and is an invitation to SQL injection attack (in the case of user input). Use it iff you are absolutely sure in your data.
string_split
which can be used here. The function splits a string with separators into a table t(value)
.string interests="a1, a2, b3, c4";
(No single quot here) and query
var query = @"SELECT type, id, owner_id
FROM entities
WHERE type = 'interest'
AND id IN (select value from string_split(@interests,','))
AND owner_id IN (select value from string_split(@users,','))";
For earlier versions you can create UDF with the same functionality.
create function dbo.split_string(@input varchar(max), @separator varchar(2))
returns table as
return
(with cte as(
select cast('<v>'+ REPLACE(@input, @separator, '</v><v>') +'</v>' as xml) x
)
select t.v.value('.[1]', 'varchar(max)') [value]
from cte
cross apply x.nodes('v') t(v))
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.