I'm having some issues with selecting the same model twice and more times with ORMLite.
My query does various LeftJoin<Model1,Model2>, and then it does something like this:
.LeftJoin<Model2, Model3>((x, y) => x.id1== y.id1, dbConnection.JoinAlias("Alias1")
.LeftJoin<Model2, Model3>((x, y) => x.id2 == y.id2, dbConnection.JoinAlias("Alias2")
.LeftJoin<Model2, Model3>((x, y) => x.id3 == y.id3, dbConnection.JoinAlias("Alias3")
.LeftJoin<Model2, Model3>((x, y) => x.id4 == y.id4, dbConnection.JoinAlias("Alias4"))
How can I use SelectMulti to get 4 times Model3? I mean something like this:
db.SelectMulti<Model1,Model2,Model3,Model3,Model3,Model3>(query);
I'm sorry if I'm unclear, but I can't post the real code due to NDA.
PS. I'm working with C#
UPDATE
I've added the following code following #mythz's suggestions (it's the last part of the answer, since I cannot upgrade for now):
String customSelection = typeof(Model1).GetModelMetadata().Alias + ".*, 0 EOT," +
typeof(Model2).GetModelMetadata().Alias + ".*, 0 EOT," +
"Alias1.*, 0 EOT," +
"Alias2.*, 0 EOT," +
"Alias3.*, 0 EOT," +
"Alias4.*, 0 EOT";
Then, in my query, I added this:
.Select(customSelection);
Now I try to get the result with this:
dbConnection.Select<Model1, Model2, Model3, Model3, Model3, Model3>(query);
This leads to a compile error, which tells me that IDbConnection does not contain a definition for Select and a Select method that accepts a first argument of the type IDbConnection was not found. (Compiler tells me that in Italian, I'm rephrasing it).
The error code from the compiler is CS1061.
You wont be able to use the SelectMulti API for selecting tables with Join Aliases. There's an example of selecting from multiple tables with JOIN aliases in OrmLite's home page:
var q = db.From<Sale>()
.LeftJoin<Contact>((s,c) => s.SellerId == c.Id, db.JoinAlias("seller"))
.LeftJoin<Contact>((s,c) => s.BuyerId == c.Id, db.JoinAlias("buyer"))
.Select<Sale, Contact>((s,c) => new {
s,
BuyerFirstName = Sql.JoinAlias(c.FirstName, "buyer"),
BuyerLastName = Sql.JoinAlias(c.LastName, "buyer"),
SellerFirstName = Sql.JoinAlias(c.FirstName, "seller"),
SellerLastName = Sql.JoinAlias(c.LastName, "seller"),
});
When finer-grain customization is needed you can use Custom SQL with the Dynamic ResultSet APIs.
I've just added support for being able to specify a Custom Table Select in this commit which will let you select tables using your custom aliases, e.g:
q = db.From<Sale>()
.LeftJoin<Contact>((s, c) => s.SellerId == c.Id, db.JoinAlias("seller"))
.LeftJoin<Contact>((s, c) => s.BuyerId == c.Id, db.JoinAlias("buyer"));
var results = db.SelectMulti<Sale, Contact, Contact>(q,
new[] { "Sale.*", "buyer.*", "seller.*" })
foreach (var result in results)
{
Sale sale = result.Item1;
Contact buyer = result.Item2;
Contact seller = result.Item3;
}
This change is available from v5.0.3 that's now available on MyGet.
If you can't upgrade you can achieve the same result by using a Custom Select, e.g:
var q = db.From<Sale>()
.LeftJoin<Contact>((s, c) => s.SellerId == c.Id, db.JoinAlias("seller"))
.LeftJoin<Contact>((s, c) => s.BuyerId == c.Id, db.JoinAlias("buyer"))
.Select("Sale.*, 0 EOT, buyer.*, 0 EOT, seller.*, 0 EOT");
var results = db.Select<Tuple<Sale, ContactIssue, ContactIssue>>(q);
Related
I have a waitlist table (id, locationid, timeslotid, sessiondate, memberid, dateAdded) which contains a list of people on various waitlist for various appointments.
I am trying to retrieve a list of all waitlist records for a specific user but i also need to get the position of that record (ordered by dateAdded) so that i can see if they are in position 1, 2, 3 etc in the queue.
The following code is what i have atm for getting all user records, but it am struggling on how to join the count to this query.
db.WaitingLists.Where(x => x.MemberId == member.Id && x.LocationId == locationId && x.SessionDate >= currentLocationDate.Date).ToList();
Some suggestions would be welcomed on how to do this.
Thanks
============= UPDATE ==============
This is the SQL that provides the response I need. I am trying to prevent using a stored Proc and try and use linq to entities where possible.
select
(
SELECT count(*) RowNr
FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY CreatedDate) AS RowNr,
MemberId
FROM waitinglist where LocationId = wl.LocationId and TimeSlotId = wl.TimeSlotId and [SessionDate] = wl.SessionDate
) sub
)
as Position, * from WaitingList as wl where memberid = '00000000-0000-0000-0000-000000000000'
I haven't tested this, but it should be pretty close. Filter first by the location and date, then sort it, then use the overload of Select that gives you an index, then filter by the member ID.
db.WaitingLists
.Where(x => x.Member.LocationId == locationId && x.Member.SessionDate >= currentLocationDate.Date)
.OrderBy(x => x.DateAdded)
.Select((x, i) => new { Position = i, Member = x })
.Where(x => x.Member.MemberId == member.Id)
.ToList();
This will give you a list of anonymous objects with two properties:
Position, which is the position in the waiting list, and
Member, which is the member details
I can't say what the SQL will actually look like, and if it will be efficient.
This might work for you. I'm assuming that the queue position is across all locations and session dates. If it isn't, insert another Where clause in between db.WaitingLists and the OrderBy.
var temp = db.WaitingLists
.Orderby(x => x.dateAdded)
.Select( (r, i) => new { Request = r, QueuePosition = i + 1)
.Where(x => x.Request.MemberId == member.Id &&
x.Request.LocationId == locationId &&
x.Request.SessionDate >= currentLocationDate.Date);
You now have a list of anonymous-type objects that have the Request (my name for your type; rename it if you want to) and a second property called QueuePosition, based on the position of the requests in the queue, as represented by the WaitingList sorted by dateAdded.
If you need to extract just the Request object, you can get it this way:
var selectedRequests = temp.Select(x => x.Request).ToList();
If you want to get any entries that were in the first 3 positions, you'd do this:
var selectedRequests = temp.Where(x => x.QueuePosition <= 3).Select(x => x.Request).ToList();
Disclaimer: done from memory, not actually tested.
I have a query which I ran successfully in SQL Server Management Studio, which returns the table values shown in the screenshot
The query I used is:
SELECT tcoid, COUNT(*) ownleasetank
FROM TankProfile
WHERE ownleasetank = 3
GROUP BY tcoid
Now I'm using Entity Framework to make things easier in my sample project.
I used this method to return the table values as array object:
public async Task<Object> GetLeaseInformationPrincipal()
{
ISOTMSEntities context = new ISOTMSEntities();
var testleaseinfo = from d in context.TankProfiles
join f in context.TankOperators
on d.tcoid equals f.tcoId
where (d.ownleasetank == 3)
select new { f.tcoName, d.ownleasetank } into x
group x by new { x.tcoName } into g
select new
{
tconame = g.Key.tcoName,
ownleasetank = g.Select(x => x.ownleasetank).Count()
};
return testleaseinfo.ToList();
}
but it is not working properly. I also tried other ways, when I use where and groupby method in Entity Framework it doesn't working properly for me.
Does anybody know the solution for this?
It's very simple with LINQ methods:
context.TankProfiles
.Where(t => t.ownleasetank = 3)
.GroupBy(t => t.tcoid)
.Select(g => new {g.Key, g.Count()})
.ToArray();
I have no idea why in your C# version of the query you have such opeartions such join, while your SQL query is very simple. You have to rethink that :)
var c = from t in context.TankProfile
where t.ownleasetank == 3
group t by t.tcoid into g
select new { tcoid=g.Key, ownleasetank=g.Select(x => x.ownleasetank).Count() };
return c.ToList();
How do I get randomly similar data
me tried to merge different ones in the first stage but Different function does not work,
var turler= (from x in db.bird_table_ad
join e in db.kus_resim on x.tr_x equals e.kus_tur
where x.aile == item
select new GozlemTurleri
{
id = x.id,
kod = x.kod,
tr_x = x.tr_x,
en_x = x.en_x,
lt_x = x.lt_x,
turfotourl="image_resize.phpad="+e.altDIR+"/"+e.resim+"&yon="+(e.galeri=="fg"?"2":"HD2"),
aile = x.aile,
gfoto = x.gfoto
}).Distinct().ToList();
If you try to get distinct record with regarding to tr_x from database then you can use GroupBy in entity framework.
So your code will be.
.GroupBy(x => x.tr_x).Select(x => x.First()).ToList();
Instead of
.Distinct().ToList();
I want to know how many people are in a especify local, using entry and exit validation of this person. If he has entered in the local, then he will generate a transaction with a TrCode = "C0". when he comes out of the place, he will generate a TrCode = "CI". There are other types of TrCode, but it is useless for this kind o validation. i have a query that returns to me this result down bellow:
var query = from a in context.CardDB
join c in context.tblTransaction on a.CardNo equals c.CardNo
where c.TrCode == "C0" || c.TrCode == "CI"
where c.TrSiteCode == sitecode
select c;
Now I have all the rows that have the TrCode == "C0" or TrCode == "CI". But the result gives me all the transactions that the employers(CardDB) did. So the result gives a lot of transactions made of different employers. Sometimes some employer make 2 or even 3 transcations like, when he arrives and when he goes out for lunch, then he cames back etc.
I have to show in a grid just the employers that have in general count more transactions TrCode == "C0" than TrCode == "CI". So, what i have to do to count the transcations of only the employers with the same ID, and, when showing it in the grid, show just a row of this employers and not all the rows.
Since already, Thank you!
var queryNumberC0 = query.Where(c => c.TrCode == "C0").Select(c => c.ID).GroupBy(c => c.Value).ToList();
var queryNumberC1 = query.Where(c => c.TrCode == "C1").Select(c => c.ID).GroupBy(c => c.Value).ToList();
And to get the number of the ID y (Key is the ID of the customer):
int y = [Customer's ID];
int temp = queryNumberC0.Find(c => c.Key == y);
You don't have to specifie the ToList() at the end of the query, do what you want with the result. I just find it easier to browse
I am less experienced with Lambda expression for .NET and trying to get data from SQL using lambda expression. With below query, I am able to get data back, but do not want to use include to get all properties from other tables.
public IEnumerable<ResourceGroup> GetAllServersByApplication(string application_name, string environment_name, string status)
{
var query = _context.ResourceGroup
.Include(a => a.Application)
.Include(t => t.Type)
.Include(e => e.ServersGroup).ThenInclude(e => e.Environment)
.Include(s => s.ServersGroup).ThenInclude(s => s.Server)
.Include(s => s.ServersGroup).ThenInclude(s => s.Server).ThenInclude(s => s.Status)
.Where(a => a.Application.Name == application_name && a.ServersGroup.Any(s => s.Environment.Name == environment_name && s.Server.Status.Name == status))
.ToList();
return query;
}
Lets take an example of below include statement.
.Include(s => s.ServersGroup).ThenInclude(s => s.Server)
From s.Server, I only want to select Id,ServerName,Status, and IPAddress. These are the properties from Servers class that I created as a model.
What is the easy way to exclude all the includes and only show properties that I am interested in?
Here are my tables and its properties:
Status table:
Id, Name
Application table:
Id, Name
Servers table:
Id, ServerName, Status
Environments table:
Id, Name
ResourceGroup table:
Id, Name, Application_Id, Environment_Id
ServersResourceGroup table:
Id, Server_Id, Resource_Id
UPDATE 1:
var query = _context.ResourceGroup
.SelectMany(rg => rg.ServersGroup
.Select(sg => new
{
ResourceName = rg.Name,
ApplicationName = rg.Application.Name,
ServerName = sg.Server.ServerName,
EnvironmentName = sg.Environment.Name,
Status = sg.Server.Status.Name
})).Where(a => a.ApplicationName == application_name && a.EnvironmentName == environment_name && a.Status == status).ToList();
return query;
And error from red line on query variable:
UPDATE 2:
Here is the query syntax:
var query = from rg in _context.ResourceGroup
let app = rg.Application
from sg in rg.ServersGroup
let env = sg.Environment
let srv = sg.Server
let stat = srv.Status
where app.Name == application_name
&& rg.ServersGroup.Any(s => s.Environment.Name == environment_name
&& s.Server.Status.Name == status)
select new
{
ResourceGroupName = rg.Name,
ApplicationName = app.Name,
ServerName = srv.ServerName,
Alias = srv.Alias,
IPAddress = srv.IPAddress,
Type = rg.Type.Name,
Status = stat.Name
};
return query;
Here is the red line error I get in query variable:
Your help is really appreciated. :)
Thanks,
Ray
With lambda expressions, you can use SelectMany to flatten 1-n associations into a 1 dimensional list (i.e. parent and child properties side-by-side). In your case, judging from the Where clause, I think only ResourceGroup - ServerGroup is 1 - n, so it should be something like:
var query = _context.ResourceGroup
.SelectMany
(
rg => rg.ServersGroup
.Select(sg => new
{
ResourceGroup = rg.Name,
Application = rg.Application.Name,
Server = sg.Server.ServerName,
// etc.
})
)
Of course it's good to know how to use lambda expressions, but there's really no point in using them when query syntax makes for much better comprehensible code.
The equivalent in query syntax is:
var query = from rg in _context.ResourceGroup
let app = rg.Application
from sg in rg.ServersGroup
let env = sg.Environment
let srv = sg.Server
let stat = srv.Status
where app.Name == application_name
&& sg.ServersGroup.Any(s => s.Environment.Name == environment_name
&& s.Server.Status.Name == status)
select new
{
ResourceGroup = rg.Name,
Application = app.Name,
Server = srv.ServerName,
// etc. use any property from rg, app, sg, srv, stat
};
As you see -
n - 1 associations are represented by a let statement (which really only helps here to shorten the references in the select)
1-n associations are represented by the from ... from syntax, which is query syntax for SelectMany.
I didn't change the Where clause in the query syntax. Maybe you can use ...
where app.Name == application_name
&& env.Name == environment_name
&& stat.Name == status)
... but note that this is different. The original where returns all ResourceGroup having at least one ServerGroup meeting the condition (and maybe other groups with different environments and statuses). The other where only returns data with environments and statuses equal to the search parameters.
Don't Include all the related tables, but Select all the fields you need. You might find it easier to make a new class to hold the data.
Sorry if I can't make a real query statement here, but your question doens't specify the fields you need.