Linq collection with not like? - c#

I have a dataGridView with multiple server roles. I'd like to get a collection of server names with roles "not like" webSrvr or client. For example.. DGV:
Servers | Server 1 | Server 2 | Server 3 | Server 4 | Server 5
Role | Database | Proxy | WebSrvr | Client | DC
Is there an easy linq statement to pull the Server 1, 2 and 5 column headers (names)? The reason I'd want to use "not like" or the equivalent is because the roles can have additional values at the end of it. Thoughts?

You could do pretty much what you want ...
var your_name = from str in your_list_source_here
where (str == some_condition)
select ( new { create your object here } )
you could just have the columns you want in the create your object here
here's an example from Linqpad , to illustrate how you can use the new object ...
var words =
from word in "The quick brown fox jumps over the lazy dog".Split()
orderby word.ToUpper()
select word;
var duplicates =
from word in words
group word.ToUpper() by word.ToUpper() into g
where g.Count() > 1
select new { g.Key, Count = g.Count() };
His objects will have the letter and the amount of time it repeats...

Related

C#, MVC4 - EF Linq searches

Ok, so i have two questions. The first is, let's say that i have an EF called "EntitiesDefinitions", which holds a data table named "stringData" where each cell is defined as a varchar(100) like so:
----------------------------------------------
| | column1 | column2 | column3 | ... |
----------------------------------------------
| row1 | "1,2,3,4" | "5,6,7,8" | "9,a,b,c" | ... |
----------------------------------------------
| row2 | "d,e,f,g" | "h,i,j,k" | "l,m,n,o" | ... |
Each cell contains 4 pieces of information separated by a comma. So what i would like to know is, if there's a way for me to perform a Linq search for the (as an example) the 2rd piece of information of every cell in column1?
using (EntitiesDefinitions ef = new EntitiesDefinitions())
{
var v = (from a in ef.stringData where (a.column1... == "e") select a);
}
I know I could just make 4 columns per cell (column1_1, column1_2, ...column2_1, column2_2,...), but that wouldn't work if i get a table with +250 original columns. So is there a way to perform such searches?
The other question is also related to this. Back in ASP.NET i could send queries to my sql using a string like this:
var stringSql = "SELECT * FROM" + "stringData" + "WHERE ([" + "column1" + "] =" + "e" + ")" + "ORDER by ["+ "column1" +"] ASC;"
Basically, i could define which tables to search for given a string value that represented that property/column. Is there a way to do that with EF linqs?
using (EntitiesDefinitions ef = new EntitiesDefinitions())
{
var v = (from a in ef.stringData where (a.["column1"]... == "e") select a);
}
I'm fairly new with MVC and EF, so I would like to know if this is possible.
From what I understand from your question you can try this out if u sure its always not null:
var res = ef.stringData.Where(c => c.column1.Split(',')[1] == "e")
And for the Second Question where you type "ef.stringData" the name of the table you are querying is "stringData" there is no other way to specify the table name or only if you want to write raw sql queries in EF.
After Fehintola suggestion i was able to do more research specific to those subjects and I was able to find a solution for both questions. In case anyone is interested here's what i came up with:
For the first question, while is not elegant, we can encapsulate data inside in specific characters/delimiters and then we can process search results in nested searches. For example:
using (EntitiesDefinitions ef = new EntitiesDefinitions())
{
//Data could look like";1;*2*&3&#4#"
var v = (from a in ef.stringData where select a); //to store the table
v = c.Where(f => f.column1.Contains("*2*")) //look for the second value
v = x.Where(f => f.column1.Contains("#4.3#"));//look for the forth value
//Do some other stuff...like sending the data to a table
}
For the Second question, you can make raw sql queries like this:
string sqlExample = #"SELECT VALUE a FROM ef.stringData AS a WHERE (a.column1 == '*2*')";
var test = ef.CreateQuery<stringData>(sql).AsQueryable();
This was you can just have variables placed in the sqlExample string to build your query dynamically and you'll get back a IQueryable object you can use to, for example, pass into a table.
I hope this helps someone in the future and thanks to everyone that provided suggestion.

Linq to SQL duplicate rank

I'm trying to build a leaderboards based on an int score. I'm pulling the records out and calculating the rank like so:
//Base query
var query = UoW.Repository<UserProfile>().Get().OrderByDescending(u => u.Points);
//Fetch the data including a groupby count
var data = await query
.Skip(skip)
.Take(pageSize)
.Select(u => new UserListItem
{
Points = u.Points.ToString(),
Username = u.DisplayName,
Rank = query.Count(o => o.Points > u.Points) + 1 //Calculates the rank (index)
})
.GroupBy(u => new { Total = query.Count() })
.FirstOrDefaultAsync();
This works fine except when I have 2 or more values with the same points it duplicate the position. I need it to be continuously incremented regardless of ties. This is how is currently displays the results:
Rank | User | Points
1 | User 1 | 456
2 | User 2 | 420
3 | User 3 | 402
4 | User 4 | 380
4 | User 5 | 380
Any idea how I can get it to auto increment correctly?
The solution is to add more conditions to the Rank function, to determine which comes first when the scores are tied. It could even be ranking by username a- > z if you like.
Answers to point you in the right direction to use multiple criteria can be found in this SO answer.

Implementing the All functionality in SQL

I'm trying to write an SQL query where all of a certain group meets a condition.
Update
The Simplifed Table Structure would look like this
ID, TitleID, BlockFromSale
---------------------------
1 | 1 | true
2 | 1 | true
3 | 1 | true
4 | 2 | false
5 | 2 | true
this table would only return the the items TitleID 1.
In actuality I only need the title ID and not the whole item but either will satisfy the conditions.
How Could I write This Linq Query in SQL?
var Query = Data.Items.GroupBy(t => t.TitleID).Where(i => i.All(b => b.BlockFromSale == true));
I try to look at the Sql Query but it just instantly casts it to an object.
Basically I just Need a query that Grabs out all TitleIDs who for each item BlockFromSale is set to true so for the example from the table above it would only return TitleID, 1
It is possible to see the generated SQL of a LINQ query by using the Log property of the query. How to: Display Generated SQL shows an example of this. Basically, the web site shows this example:
db.Log = Console.Out;
IQueryable<Customer> custQuery =
from cust in db.Customers
where cust.City == "London"
select cust;
foreach(Customer custObj in custQuery)
{
Console.WriteLine(custObj.CustomerID);
}
If you want to check predicate p for all rows of a set you can write
NOT EXISTS (... WHERE NOT(p))
Because All(p) == !Any(!p) in pseudo-syntax.
I would guess that ORMs do it this way, too.
There isn't an easy way to do what your asking but a simple but some what slow way would be to use a subQuery
SELECT DISTINCT i.TitleID
FROM Items i
WHERE i.TitleID not in
(SELECT DISTINCT TitleID
FROM items it
WHERE it.BlockFromSale = 0)
so it will remove the titleids who have a false.

Gnarly Linq query

Have the following table structure
I need the count of transcriptions by statuses where the records do not have a workflow folder. This does the trick:
from p in Transcriptions
where p.WorkflowfolderID == null
group p by p.TranscriptionStatus.Description into grouped
select new
{
xp=grouped.Key,
xp1= grouped.Count(),
}
Now I need to add the number of records where the Dueon date is in the past as in it is past the due by date.Something like
EntityFunctions.DiffHours(p.DueOn,DateTime.Today)>0
How do I include this in the resultset without firing 2 SQL queries? I am happy to get it as a third column with the same value in every row. Also is there anyway to get the percentage into the mix as in:
Status | Count | % |
------------------------------
Status1 | 20 | 20%
Status2 | 30 | 30%
Status3 | 30 | 30%
Overdue |20 | 20%
I have added Overdue as a row but perfectly happy to get it as a column with the same values.
Edited Content
Well this is the best I could come up with. Its not a single query but there is only one SQL trip. The result is:
Status | Count
----------------
Status1 | 20
Status2 | 30
Status3 | 30
Overdue |20
var q1= from p in Transcriptions
where p.WorkflowfolderID == null
group p by p.TranscriptionStatus.Description into grouped
select new
{
status= (string)grouped.Key,
count= grouped.Count()
};
var q2 =(
from p in Transcriptions select new {status = "Overdue",
count = (from x in Transcriptions
where x.DueOn.Value < DateTime.Now.AddHours(-24)
group x by x.TranscriptionID into
grouped select 1).Count() }).Distinct();
q1.Union(q2)
It is a Union clause with the % calculation to be done once the results are returned. The weird thing is that I couldn't figure out any clean way to represent the following SQL in a LINQ statement which has resulted in the rather messy LINQ in the var q2.
SELECT COUNT(*) , 'test' FROM [Transcription]
You can add a condition to Count:
from p in Transcriptions
where p.WorkflowfolderID == null
group p by p.TranscriptionStatus.Description into grouped
select new
{
xp=grouped.Key,
xp1= grouped.Count(),
xp2= grouped
.Count(p => EntityFunctions.DiffHours(p.DueOn, DateTime.Today) > 0)
}
By the way, with entity framework you can also use p.DueOn < DateTime.Today.
#Gert Arnold
from p in Transcriptions
where p.WorkflowfolderID == null
group p by p.TranscriptionStatus.Description into grouped
select new
{
status= (string)grouped.Key,
count= grouped.Count(),
overdue= grouped.Count(p => p.DueOn < EntityFunctions.AddHours(DateTime.Today, -24)),
}
The above query does work as I wanted it to . It produces the outcome in the format
Status| Count | Overdue
----------------------
status1|2|0
status2|1|1
The only downside is the generated SQL is running 2 queries BOTH with inner joins . My original idea with the Union may be a better idea performance wise but you answered my query and for that I am grateful.
Can this query be represented in some other cleaner manner than my above attempt -
SELECT COUNT(*) , 'test' FROM [Transcription]

List of unique strings in database table using Linq?

I have a "Tickets" table with somewhat following structure (removed unnecessary columns)
int | string | int |
ID | Window | Count |
------------------------
0 | Internet | 10 |
1 | Phone | 20 |
2 | Fax | 15 |
3 | Fax | 10 |
4 | Internet | 5 |
. | . | . |
. | . | . |
And I have mapped this table to a class "Ticket". So I can get all records like this:
var tickets = from t in db.Tickets
select t;
Now I need to get the list of unique window names in the table. For above table, list would look something like:
Internet
Phone
Fax
Is there anyway to create this list without fetching all records and iterating over them?
I am using SQL Server 2008 express edition.
EDIT:
Thanks for the answers guys it solved the above problem. Just being greedy but is there any way to also get the total of count for each window. For example:
Internet = 15
Phone = 25
Fax = 20
How about:
var tickets = db.Tickets.Select(t => t.Window).Distinct();
I prefer to only use query expressions when I'm doing more than one operation, but if you like them the equivalent is:
var tickets = (from t in db.Tickets
select t.Window).Distinct();
To get the counts, you need to group:
var tickets = from t in db.Tickets
group t by t.Window into grouped
select new { Window=grouped.Key,
Total=grouped.Sum(x => x.Count) };
foreach (var entry in tickets)
{
Console.WriteLine("{0}: {1}", entry.Window, entry.Total);
}
Note that this should all end up being performed at the database side - examine the SQL query to check this.
var query2 = from ticket in db.tickets
group window by ticket.Window into result
select new
{
Name = result.Window,
Sum = result.Sum(i => i.Count)
};
The query will be evaluated inside the store.
var windows = db.Tickets.Select(ticket => ticket.Window).Distinct();
Linq Samples Part 11 by Bill Wagner should help you. Just call the Distinct() function on your Linq result. It's as simple as that.
var tickets = (from t in db.Tickets
select t).Distinct();
[EDIT]
Concering the numbers of the occurences, see this example as a hint.
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 5 };
var numberGroups =
from n in numbers
group n by 5 into g
select g;
g.Count(); // occurences
You can use the .Distinct() operator - it'll make a SELECT DISTINCT to the database, giving exactly what you ask for.

Categories