LINQ to SQL - Struggling with query - linq-to-sql

I have a table with server names and logins. I need to retrieve the logins that are common across a group of servers.
Given the following data:
ServerName Login
-------------------------------
Server1 User1
Server2 User1
Server2 User2
I would pass in Server1,Server2 and get back only User1 as User2 is not associated Server1.
Can anyone tell me how this would be achieved in LINQ to SQL?
I have tried Contains but that returns me all users on any of the servers which is kind of the opposite to what I'm looking for.
EDIT: One of my colleagues managed to write the SQL version of what I'm after....
SELECT Login
FROM ServerLogins
WHERE ServerName IN ('Server1', 'Server2')
GROUP BY Login
HAVING count(Login) = 2
but neither of us know how to translate this into a LINQ query.
ADDITIONAL EDIT:
With Ryan's help and some Googling of the differences in LINQ between VB and C# I got the following to work.
Dim logins = From l In dc.ServerLogins _
Where servers.Contains(l.ServerName) _
Group l By l.Login Into Group _
Where Group.Count() = servers.Count _
Select Login
Thanks again to everyone for their help.
Nick

Here is what I came up with. You'll probably want to check and find out what SQL it actually generates if you're worried about it.
List<string> servers = new List<string>{"Server1", "Server2"};
var logins = from l in context.ServerLogins
where servers.Contains(l.ServerName)
group l by l.Login into g
where g.Count() == servers.Count
select g.Key;

Personally I think this is a good place NOT to use Linq to SQL and instead to use either a sproc or a standard SQL query. I think that even if you were to come up with the correct query in Linq, it would not be very readable and/or efficient.
The SQL you would have would look something like this:
SELECT Login
FROM ServerLogins
WHERE ServerName IN ('Server1', 'Server2')
GROUP BY Login
HAVING COUNT(*) = 2
Note that the "2" in the last line should be replaced with the number of server names in the list above ("IN ('Server1', 'Server2')").

As long as there's a reasonable practical limit on the # of servers being passed in I'd go with something like this:
public ICollection<Login> GetLoginsForServers(params string[] servers)
{
if (servers == null || servers.Length == 0)
return new List<Login>();
var logins = db.Logins.Where(p => p.ServerName == servers[0]);
for (int i=1; i<servers.Length; i++)
{
logins = logins.Intersect(db.Logins.Where(p => p.ServerName == servers[i]));
}
return logins.ToList();
}
Basically you're starting with all the logins associated with the first server then limiting it by those associated with each subsequent. Since the query doesn't get executed until ToList() you still only query the database once, and although the query itself is bound to be ugly, the hope is that the LINQ2SQL provider generates something that will result in an efficient query plan.

Related

Method has no supported translation to SQL(Linq to Sql)

After I execute a query on the database, and try to print the result of that execution, I got this error:
Method has no supported translation to SQL.
My code:
Table<User> users = DAL.DALConnection.Database.GetTable<User>();
var query = from user in users
where user.Get_UserName().ToString() == username
select user;
foreach (User user in query)
Console.WriteLine(user);
Is Get_UserName() a C# function you've written in your code? If so, the error coming back makes sense, because SQL Server doesn't know about that function.
Instead, you would probably want to do something like where user.username == username, assuming your table has a username field.

How to get result from a luaSQL query?

So I'm trying to do a count query within a command from lua SQL, using a mySQL database. I want to get the current count of users within a table, however I'm quite lost with using lua as a language and incorporating a database to it.
So far, this is what I have:
exec,err = connect:execute("SELECT count(user_id) AS count FROM Users")
testString = string.format("%d", exec:numrows())
if exec:numrows() == 0 then
send_msg(receiver, teststring, ok_cb, false)
end
I've checked it with another script and it's value that it returns is 1, however I want to get the value within the row... How would I go about doing this with luaSQL?
Okay instead of making this harder on myself, I just decided to remove the count command from the SQL statement, and use the numrows statement within luaSQL, kind of like this:
exec,err = connect:execute("SELECT user_id FROM Users")
if exec:numrows() == 0 then
send_msg(receiver, "test", ok_cb, false)
end

How best to retrieve result of SELECT COUNT(*) from SQL query in Java/JDBC - Long? BigInteger?

I'm using Hibernate but doing a simple SQLQuery, so I think this boils down to a basic JDBC question. My production app runs on MySQL but my test cases use an in memory HSQLDB. I find that a SELECT COUNT operation returns BigInteger from MySQL but Long from HSQLDB.
MySQL 5.5.22
HSQLDB 2.2.5
The code I've come up with is:
SQLQuery tq = session.createSQLQuery(
"SELECT COUNT(*) AS count FROM calendar_month WHERE date = :date");
tq.setDate("date", eachDate);
Object countobj = tq.list().get(0);
int count = (countobj instanceof BigInteger) ?
((BigInteger)countobj).intValue() : ((Long)countobj).intValue();
This problem of the return type negates answers to other SO questions such as getting count(*) using createSQLQuery in hibernate? where the advice is to use setResultTransformer to map the return value into a bean. The bean must have a type of either BigInteger or Long, and fails if the type is not correct.
I'm reluctant to use a cast operator on the 'COUNT(*) AS count' portion of my SQL for fear of database interoperability. I realise I'm already using createSQLQuery so I'm already stepping outside the bounds of Hibernates attempts at database neutrality, but having had trouble before with the differences between MySQL and HSQLDB in terms of database constraints
Any advice?
I don't known a clear solution for this problem, but I will suggest you to use H2 database for your tests.
H2 database has a feature that you can connect using a compatibility mode to several different databases.
For example to use MySQL mode you connect to the database using this jdbc:h2:~/test;MODE=MySQL URL.
You can downcast to Number and then call the intValue() method. E.g.
SQLQuery tq = session.createSQLQuery("SELECT COUNT(*) AS count FROM calendar_month WHERE date = :date");
tq.setDate("date", eachDate);
Object countobj = tq.list().get(0);
int count = ((Number) countobj).intValue();
Two ideas:
You can get result value as String and then parse it to Long or BigInteger
Do not use COUNT(*) AS count FROM ..., better use something like COUNT(*) AS cnt ... but in your example code you do not use name of result column but it index, so you can use simply COUNT(*) FROM ...

Linq to SQL Server - difficulty with sub-query example

I have a SQL Server table that contains the following fields:
SessionId (guid)
Message (varchar)
Timestamp (datetime)
What I need to do is to pull out the FIRST record for EACH SessionId using LINQ to SQL (ideally as a lambda, but query syntax would be useful)
It's relatively simple to do this with t-SQL....
SELECT al.Message, al.SessionId, al.Timestamp
FROM AppLog AS al
WHERE al.Timestamp =
(select MIN(al2.Timestamp) from ApplicationLog as al2 where al2.SessionId = al.SessionId)
I've tried to do the same with a Lambda query (using joins) but it's just not working...
Any/all help will be much appreciated.
Thanks in advance
Griff
I don't know if I'm being simplistic-- but if this is one table, then this should work?
db.Applog.GroupBy(a=>a.SessionID).Select(g=>g.OrderBy(m=>m.Timestamp).First());
You tried using linquer?
http://www.sqltolinq.com/
Query syntax might look a bit nicer than a lambda -
var x = from al in db.AppLog
where al.Timestamp ==
(from al2 in db.ApplicationLog on al2.SessionId equals al.SessionID
select al2.Timestamp).Min())
select new
{
al.Message,
al.SessionId,
al.Timestamp
};

Trying to get the memberid from table

I am trying to get the memberid from database according to text entered in the textbox like this way
String sql =#" SELECT member_Id FROM members where (member_Firstname,'',member_Lastname) ="+tbMemberName.Text;
How can this be done?
Try this:
String sql =#" SELECT member_Id FROM members where CONCAT(member_Firstname,'',member_Lastname) = '"+tbMemberName.Text+"'";
Also, this is vulnerable to sql injection.
Due to security and performance reasons, I would personally split the members's name in first/ last before compiling the query. Now, I'm not familiar with the language you use to call this query, but I'll formulate something that will hopefully make sense, regardless of it's stupidity:
String sql =#" SELECT member_Id FROM members WHERE member_Lastname = "+safely_escaped(tbMembername.Last.Text)+" AND member_Firstname = "+safely_escaped(tbMembername.First.Text)+"
This will allow for a more precise analysis of the names before inserting it into the query and it will allow you to use an index (which is not possible with any of the previously shown examples). Just to be clear, the index, most efficiently in this case, would be INDEX (member_Lastname, member_Firstname).
If that's C# that you're writing, as you've commented, you'll want to start using parameters to avoid SQL injection.
string getMember= #"SELECT member_Id FROM members
WHERE member_Firstname like #userText
OR member_Lastname like #userText;";
MySqlCommand m = new MySqlCommand(getMember);
m.Parameters.AddWithValue("#userText", tbMemberName.Text + "%");
var reader = m.ExecuteReader();