db.raw with more than one paremter with knex - postgresql

This actually works in knex:
knex.raw('select * from users where id = ?', [1])
I am trying to use more than one value as parameters, repeating some of them. Something like this:
knex.raw('select * from users where id = 1? and name = 2? and firstName = 2?', [1, 'someName'])
How can I achieve that?

you can do something like this also:
var params = {x1:1,dude:10};
return knex.raw("select * from foo where x1 = :x1 and dude = :dude",params);
it's not the first example, but it's documented here.

It looks like the obvious quick solution is to simply repeat your array elements.
knex.raw('select * from users where id = 1? and name = 2? and firstName = 3?', [1, 'someName', 1])
I don't know knex, but there's nothing wrong with this solution either.
EDIT
A different approach is to use simple string interpolation through a library like kiwi:
var interpolateObject = {
id: 'some_id',
name: 'some_name',
firstName: 'some_first_name'
};
var query = Kiwi.compose(
"select * from users where id = %{id} and name = %{name} and firstName = %{firstName}",
interpolateObject
);
knex.raw(query);
Checkout kiwi.js

Related

How to Data Fetch using Entity Framework in dotnet core

I have a table called "UserAnswers".below screenshot contains table data
I want to get data by surveyId and group by CreatedBy column.
for an example
There is a user called "amara#gmail.com".this user contains 4 records for a SurveyId.
I want to get this like below
Answers : [
{"2"},
{"1","0","1","1"},
{"1","2","4","3"},
{"Blue"}]
But my code returns this array for every rows.I meant duplicate records returning.
Here is my code
var qstns = await (from uans in _context.UserAnswers
where uans.SurveyId == id
select new UserAnswersReturnDto
{
UserEmail = uans.CreatedBy,
Qustns = (from ans in _context.UserAnswers
where ans.CreatedBy == uans.CreatedBy
select new UserAnswersSet
{
QNo = ans.QNo,
Ansrs = JsonConvert.DeserializeObject<JArray>(string.IsNullOrEmpty(ans.Answers) ? "[]" : ans.Answers)
}).ToArray()
}).ToListAsync();
So how to solve this issue.I opened many questions for this problem,but no one answered.Please help me.Thanks in advanced
You need to actually group your data before returning:
I used LINQ Lambda notation, but it should be quite easy to translate back to query if you're so inclined:
var qstns = _context.UserAnswers.Where(uans => uans.SurveyId == id)
.GroupBy(uans => uans.CreatedBy)
.Select(grans => new UserAnswersReturnDto {
UserEmail = grans.Key,
Qustions = grans.Select(ans => new UserAnswersSet() {
QNo = ans.QNo,
Ansrs = ans.Answers
}).ToList()
} ).ToList();
I didn't have time to double-check this, but I hope it serves as a guide to help you solve your issue!
There is no group by statement in your linq query.

How do I write a Linq query that needs a subquery?

I need to extract some information about support tickets from a database. Each ticket is associated with a medical imaging system, and each system may or may not have service cover associated with it. If it does, there may be multiple service cover entries, but only one that interests us.
I know this is not valid Linq, but what I would really like to do is the following...
var tickets = cxt.SupportTickets
.Select( t => new {
ID = t.ID,
Customer = t.Customer.Name,
var cover = t.System.CoverItems.FirstOrDefault(ci => // some query)
CoverLevel = cover?.Level.Name,
Expiry = cover?.Expiry.ToLongDateString()
});
Is there any way to do this? I know that I could repeat the t.CoverItems.FirstOrDefault(...) bit for every bit of data I want from the cover, but apart from the absolutely awful code mess this would produce, it would be very inefficient, as it would need to do the same subquery multiple times for every ticket.
I thought about breaking it all up into a foreach loop, but then I couldn't see how to create the tickets collection. I can't create an empty collection and then add objects to it, as they are anonymous types, and I wouldn't like to think about how you would specify the generic type!
Anyone any ideas?
You could improve readability:
var tickets = cxt.SupportTickets
.Select(t => new {
Ticket = t,
CoverItem = t.System.CoverItems.FirstOrDefault(ci => // some query)
})
.Select(x => new {
ID = x.Ticket.ID,
Customer = x.Ticket.Customer.Name,
CoverLevel = x.CoverItem?.Level.Name,
Expiry = x.CoverItem?.Expiry.ToLongDateString()
});
You could use query notation instead to use let clause:
var query=from t in cxt.SupportTickets
let cover = t.System.CoverItems.FirstOrDefault(ci => some query)
select new {
ID = t.ID,
Customer = t.Customer.Name,
CoverLevel = cover?.Level.Name,
Expiry = cover?.Expiry//.ToLongDateString()
};
At the end is going to do the same that #TimSchmelter answer, but for things like that you can use let. Another thing, I'm almost sure ToLongDateString() method is not supported in EF.
I've tried this (If you wanted to develop a subQuery separately, because of SoC principle):
var innerQuery = cxt.SupportTickets
.Where(artist => artist.coverId == SomeParameter)
.Select(artist => new {
artistId = artist.artistId,
artistCompleteName = artist.artistName,
artistMasterPiece = artist.CoverName
});
var tickets = cxt.SupportTickets
.Where(
t => innerQuery.Contains(t.coverId)
)
.Select( t => new {
ID = t.ID,
Customer = t.Customer.Name,
var cover = t.System.CoverItems.FirstOrDefault()
CoverLevel = cover?.Level.Name,
Expiry = cover?.Expiry.ToLongDateString()
});

MongoEngine remove string from ListField

code:
class Users(db.Document, UserMixin):
first_name = db.StringField()
last_name = db.StringField()
username = db.StringField(unique=True)
password = db.StringField()
email = db.StringField()
following = db.ListField(db.StringField(), default=[])
role = db.ListField(db.StringField(), default=["user"])
confirmed = db.BooleanField(default=False)
confirmed_on = db.DateTimeField()
so if I wanted to remove a certain string from the Users.following field
Users.objects(username="some_user").update(pull__following=["some_string"])
and then save it?
because I've tried this and it won't remove the string from the following listField
If you want to remove one element from your list you need to use the pull modifier which takes a single value not a list as you are doing so the correct query is:
Users.objects(username='some_user').update(pull__following='some_string')
You can also remove several element from your "following" list using the pull_all modifier; and in this case you pass in a list of value.
Users.objects(username='some_user').update(pull_all__following=['one_string', 'another_string'])

Combinations of Where Criteria - Still parameterized query - Dapper

I have a Dapper query as follows
Public void GetAllCusomers(string CustmoerId, StringFirstName, String LastName, String Gender)
{
TblCustomer tblCustomer = new TblCustomer();
using (var sqlConnection = new SqlConnection(“DatabaseConncetionString"))
{
sqlConnection.Open();
//tblCustomer = sqlConnection.Query<TblCustomer >("SELECT * FROM tblCustomer WHERE CustomerId = #CustomerID" AND FirstName = #FirstName……………, new { CustomerID = CustomerId,……………. }).ToList();
tblCustomer = sqlConnection.Query<TblCustomer >("SELECT * FROM tblCustomer WHERE CustomerId = #CustomerID", new { CustomerID = CustomerId }).ToList();
sqlConnection.Close();
}
}
The question is how to build the query? In the above method user can provide value to any parameters that he wishes to query. If the parameter value is blank that will not be used in the WHERE criteria. I will be using all the supplied parameters in the where criteria with AND operations.
Without Dapper it is easy to build the dynamic query by concatenating the SQL statement depending upon the supplied parameters. How to build these queries in Dapper without compromising the parameterized feature.
Thank you,
Ganesh
string sql = "SELECT * FROM tblCustomer " +
"WHERE CustomerId = #CustomerID AND FirstName = #FirstName"; // ...
var parameters = new DynamicParameters();
parameters.Add("CustomerId", customerID);
parameters.Add("FirstName", firstName);
// ...
connection.Execute(sql, parameters);
You would do it similar to how you build a dynamic query. Build your string dynamically (based on user input), only including filters in the Where clause as needed.
Exmpale:
var query = new StringBuilder("select * from users where ");
if(!string.IsNullOrEmpty(firstname)) query.Append("FirstName = #FirstName ");
As far as passing in the parameters, you can either construct an object that includes all of your possible parameters with values to pass in:
new {FirstName = "John", LastName = "Doe"}
or, if you only want to pass in parameters that will actually be used, you can build a Dictionary<string,object> that contains only those parameters you need to pass in:
new Dictionary<string,object> { {"FirstName", "John" } }

How can I use the same ObjectId for 2 collections using MongoEngine ReferenceField?

I have a fairly heavy User document class, and I would like to cut it in two pieces: the user's profile (name and avatar) in a UserProfile document and the rest in a User document, like this (using MongoEngine):
from mongoengine import *
class User(Document):
login = StringField()
password = StringField()
posts = ListField(ReferenceField("Post", dbref = False))
#... a bunch of other fields
class UserProfile(Document):
name = StringField()
avatar = URLField()
I would like to have the same ObjectId for both the UserProfile and the User, so that I only need one ObjectId to reference both the User and the UserProfile. After all, it's really a one-to-one relationship, and since a user can author many posts, I don't want to embed her profile in the posts themselves. When creating a user document, I would immediately create the corresponding profile document like this:
john = User.objects.create(login = "john", password = "super!password")
john_profile = UserProfile.objects.create(id = john.id, name = "John Smith",
avatar = "http://www.example.com/img/photo.jpg")
So far so good. Now I have a Post document with an author field that references the User document:
class Post(Document):
author = ReferenceField("User", dbref = False)
text = StringField()
I would like to add an author_profile reference, based on the same ObjectId. I tried this:
class Post(Document):
author = ReferenceField("User", dbref = False)
author_profile = ReferenceField("User", db_field = "author", dbref = False)
text = StringField()
But I get the following exception:
mongoengine.base.InvalidDocumentError: Multiple db_fields defined for: author
So it seems that I have to do so "manually". Something like this perhaps:
class Post(Document):
author = ReferenceField("User", dbref = False)
text = StringField()
#property
def author_profile(self):
if hasattr(self, "_author_profile"):
return self._author_profile
self._author_profile = UserProfile.objects.get(id = self._data["author"].id)
return self._author_profile
I guess it's not that bad, but isn't there a better solution?
Thanks.
Note: I read the mongodb documentation about one-to-one relationships, as well as the mongoengine ReferenceField documentation, but it did not help me on this specific question.
You'd have to store the same id twice to do this:
class Post(Document):
author = ReferenceField("User", dbref = False)
author_profile = ReferenceField("UserProfile", dbref = False)
text = StringField()
I'm not sure if that brings any benefits to your solution - there maybe an improvement in the number of queries to dereference, but I'd have to test that!
I ended up writing this:
def user_profile(reference_name):
attrib_name = "_" + reference_name + "_profile"
def user_profile_getter(self):
if not hasattr(self, attrib_name):
reference = self._data.get(reference_name, None)
if not reference:
return None
setattr(self, attrib_name, UserProfile.objects.get(reference.id))
return getattr(self, attrib_name)
return property(user_profile_getter)
My Post class now looks like this:
class Post(Document):
author = ReferenceField("User", dbref = False)
author_profile = user_profile("author")
text = StringField()
Whenever I add a ReferenceField that points to the User class, I also add such a user_profile (read-only) reference. Note that if you only access the author_profile, it will not load the author, and vice versa.