How Linq query fetch data from multiple tables without using join - c#

I have 3 tables in my database which have no relation with each other. what i want is to implement the search operation on my website. So that when a word is submit in search box the query go through all the tables and fetch the data wherever it find that word. I can fetch the data from single table.
public ActionResult Searchresult(string searchString)
{
var article = (from c in db.Tbl_Article select c );
article = article.Where(s => s.Article_Title.Contains(searchString));
var blog = (from c in db.Tbl_Blog select c );
blog = blog.Where(s => s.Blog_Title.Contains(searchString));
var history = (from c in db.Tbl_History select c);
history = history.Where(s => s.Title.Contains(searchString));
var result = article.Select(x => x.Article_Title).Union(blog.Select(x => x.Blog_Title)).Union(history.Select(x => x.Title)).ToList();
// ViewBag.result = result.ToString();
return View(result);
}
Please don't confuse about what i return in action method, its a very long and unnecessary code for that question.
By using this code I successfully get the search result from one table.
Now I want same result from all the tables present in the database. that's where I'm stuck. I searched so many article for that but didn't find any solution that's in the last I myself asking this.
Thanks

This may work
Public ActionResult Index(string searchString)
{
var query1 = (from c in db.TableArticle select c);
if (!String.IsNullOrEmpty(searchString))
{
query1 = query1.Where(s =>
s.Article_Title.Contains(searchString)
|| s.Article_Description.Contains(searchString) ||
s.Written_By.Contains(searchString) ||
s.Organisation.Contains(searchString)
||s.Source.Contains(searchString));
}
var query2 = (.......);
var query3 = (.......);
var finalResult = query1.Select(x => x.columnName).Union(query2.Select(x => x.columnName)).Union(query3.Select(x => x.columnName));
// OR
var finalResult = query1.Select(x => x.columnName).Concat(query2.Select(x => x.columnName)).Concat(query3.Select(x => x.columnName));
}

I have just implemented and checked in my local same query, and it's working fine,
The given answer is right by #Khairul Alam,
I have just optimized the code and run the same thing in my local its working fine
var searchString = "School";
if (!String.IsNullOrEmpty(searchString))
{
var query1 = _context.Jobs.Where(s =>
s.JobTitle.Contains(searchString)
|| s.LocationDescription.Contains(searchString));
var query2 = _context.Recruiters.Where(s =>
s.RecruiterName.Contains(searchString));
var query3 = _context.Sectors.Where(s =>
s.SectorName.Contains(searchString));
try
{
var finalResult = query1.Select(x => x.JobTitle).Union(query2.Select(x => x.RecruiterName)).Union(query3.Select(x => x.SectorName)).ToList();
}
catch (Exception)
{
throw;
}
contain image which output of final result
If you still getting an issue , please share some code or where exactly you getting the error , so we can solve them
hope this will be helpful to you
Thanks

Related

C# Linq nested selects not returning everything

I'm trying to select information from multiple tables via Linq. The query works if I take out the last Api query from apis in Database.PluginApis where apis.PluginId == tenantPlugin.PluginId. If I put the query back in, it results in an error System.Collections.Generic.KeyNotFoundException: The given key 'Name' was not present in the dictionary. Anyone able to see what I am doing wrong?
var results = (from tenantPlugin in Database.TenantPlugins
where tenantPlugin.TenantId == tenantId
select new TenantPlugin
{
PluginId = tenantPlugin.PluginId,
IsEnabled = tenantPlugin.IsEnabled,
TenantId = tenantPlugin.TenantId,
TenantPluginId = tenantPlugin.TenantPluginId,
Plugin = (from plugin in Database.Plugins
where plugin.PluginId == tenantPlugin.PluginId
select new Plugin
{
PluginId = plugin.PluginId,
Name = plugin.Name,
Description = plugin.Description,
ImagePath = plugin.ImagePath,
IsActive = plugin.IsActive,
Apis = (from apis in Database.PluginApis
where apis.PluginId == tenantPlugin.PluginId
select new PluginApi
{
Name = apis.Name
}).ToList<PluginApi>()
}).FirstOrDefault<Plugin>()
});
return results.ToList();
It's seems you have a perfect case to use Include() method. Try:
var results = Database.TenantPlugins
.Include(t => t.Plugin.Select(p => p.Apis))
.Where(t => t.TenantId == tenantId);

How to improve Query with linq

I'm a little bit stuck, I took an new project but there is so timeout issue due to queries.
I don't know the syntax in linq to improve one querie even if i tried multiple times.
The query is :
var contactslist = (User as CustomPrincipal).contacts;
var contacts = from m in db.ADDR_DEST.toList()
from n in contactslist
where m.ADDR_COUNTRY == n.country && m.ADDR_TPL_TYPE == n.tpl_type
select m;
But I want to dosen't launch this query before that i had different parametre so i remove the .toList() for adding some condition with
contacts.where(..);
And then I would like launch my query but i got an error with the type which must be an list<> but in this case it's a Iqueryable.
Can you help me please?
Is there an other way to launch this query after I do all my settings?
You can do something like that:
db.ADDR_DEST.Join(contactslist,
addr => new { country = addr.ADDR_COUNTRY, type = addr.ADDR_TPL_TYPE },
cont => new { country = cont.country, type = cont.tpl_type },
(addr, cont) => addr)
.ToList();
Then, if you want to choose the contactlist that meet certain requirements:
db.ADDR_DEST.Join(contactslist.Where(...).ToList(),
addr => new { country = addr.ADDR_COUNTRY, type = addr.ADDR_TPL_TYPE },
cont => new { country = cont.country, type = cont.tpl_type },
(addr, cont) => addr)
.ToList();
I hope you find it useful
Try (not tested):
var contacts = db.ADDR_DEST.Where(m => m.COUNTRY == contactslist.country
&& m.ADDR_TPL_TYPE == contactslist.tpl_type)
.ToList();
If contactslist is a list then try the following
var contacts = (from addr in db.ADDR_DEST
join cl in contactslist on
new {addr.COUNTRY, addr.ADDR_TPL_TYPE} equals new {cl.country, cl.tpl_type}
select new {addr})
.ToList();
The Linq join is easier to understand than its lambda equivalent!
There are some good examples here

Get multiple data from tables Using Entity Framework

public ActionResult Hotel_Read(string text)
{
var result = GetHotel().Where(c => c.Name.Contains(text) || c.City.Contains(text) || c.Country.Contains(text)).ToList();
return Json(result, JsonRequestBehavior.AllowGet);
}
private static IEnumerable<HotelViewModel> GetHotel()
{
using (TravelAgancyEntities1 db = new TravelAgancyEntities1())
{
var query = db.Hotels
.Include(p => p.City.Country).Distinct().ToList();
return query.Select(Hotel => new HotelViewModel
{
Name = Hotel.Name,
City = Hotel.City.City_Name,
**Line 10-** Country = Hotel.City.Country.Country_Name,//!!!
});
}
}
When I run the code without line 10, it is working successfully, but when that code is run with line 10, then it's not working.
I assume your code should run properly. the only thing that makes me suspicious, is that you are trying to retrieve all Hotel table data plus 2 other table(with include)
try this :
var q = (from x in db.Hotels.Include(c => c.City).Include(c => c.City.Country)
where x.Id == 5030
select x).Distinct().ToList();
string s = q[0].City.Country.Country_Name;
Limit your select with Where clause.
You don't need Includes here because there is no application logic involved in creation of HotelViewModel instances.
Simple query:
db.Hotels.Select(h => new HotelViewModel
{
Name = h.Name,
City = h.City.City_Name,
Country = h.City.Country.Country_Name,
}).ToList();
Will return from the DB exactly the data that you need.
When you first do Includes, and then call ToList();:
var query = db.Hotels.Include(p => p.City.Select(x => x.Country))
.Distinct()
.ToList();
You fetch form DB all the Hotel properties, all the City properties and
all the Country properties while all you really need is only their names.

c# linq syntax slow due to multiple queries in single query

I am wondering if there is a better, more efficient way to re-code the linq syntax below to make the query run faster i.e. with a single call to the database. My database is located remotely which causes this to be quite slow:
var query = (from ticket in dataClassesDataContext.Tickets.Where(TicketsToShow.And(SearchVals))
select new
{
Priority = ticket.TicketPriority.TicketPriorityName,
Ticket = string.Format(TicketFormat, ticket.TicketID),
AssetId = ticket.Asset.Serial,
OpenDate = ticket.CheckedInDate,
OpenFor = CalculateOpenDaysAndHours(ticket.CheckedInDate, ticket.ClosedDate),
Account = ticket.Account.Customer.Name,
Description = ticket.Description.Replace("\n", ", "),
Status = ticket.TicketStatus.TicketStatusName,
Closed = ticket.ClosedDate,
THIS IS THE CAUSE ====>>> Amount = GetOutstandingBalanceForTicket(ticket.TicketID),
Paid = ticket.Paid,
Warranty = ticket.WarrantyRepair,
AssetLocation = GetAssetLocationNameFromID(ticket.Asset.LocationID, AssLocNames)
}).Skip(totalToDisplay * page).Take(totalToDisplay);
if (SortOrder.ToLower().Contains("Asc".ToLower()))
{
query = query.OrderBy(p => p.OpenDate);
}
else
{
query = query.OrderByDescending(p => p.OpenDate);
}//ENDIF
The main cause for the poor performance is the code in the function GetOutstandingBalanceForTicket below which calculates the sum of all items in an invoice and returns this as a total in a string:
public static string GetOutstandingBalanceForTicket(int TicketID)
{
string result = string.Empty;
decimal total = 0;
try
{
using (DataClassesDataContext dataClassesDataContext = new DataClassesDataContext(cDbConnection.GetConnectionString()))
{
var queryCustomerTickets = from ticket in dataClassesDataContext.Tickets
where
(ticket.TicketID == TicketID)
select ticket;
if (queryCustomerTickets != null)
{
foreach (var ticket in queryCustomerTickets)
{
var queryTicketChargeItems = from chargeItem in dataClassesDataContext.ProductChargeItems
where chargeItem.ChargeID == ticket.ChargeID &&
chargeItem.Deleted == null
select chargeItem;
foreach (var chargeItem in queryTicketChargeItems)
{
total += (chargeItem.Qty * chargeItem.Price);
}
}
}
}
}
catch (Exception ex)
{
}
return total.ToString("0.##");
}
Thank you in advance.
As you pointed out this code is quite slow as a query will be required for each ticket.
to eliminate the need for multiple queries you should look at applying an inner join between the ticketsToShow and the tickets entity (on the ticketid), using groupby to provide the sum of the charges for each ticket.
This is well illustrated in the answers to LINQ: Using INNER JOIN, Group and SUM
Ideally you would probably approach it more as an eager loading all at once type of setup. However, I do not think linq2sql supports that (I know EF does). One thing you can do is avoid the nested query though. Since you already have access to the ticket table, perhaps you should just issue a Sum() on it from your select statement. Hard for me to verify if any of this is an improvement so this code is kind of on the fly if you will.
//(from ticket in dataClassesDataContext.Tickets.Where(TicketsToShow.And(SearchVals))
(from ticket in dataClassesDataContext.Tickets
//this would be where you could eager load if possible (not entirely required)
//.Include is an EF method used only as example
/*.Include(t => t.TicketPriority)//eager load required entities
.Include(t => t.Asset)//eager load required entities
.Include(t => t.Account.Customer)//eager load required entities
.Include(t => t.TicketStatus)//eager load required entities
.Include(t => t.ProductChargeItems)//eager load required entities
*/
.Where(TicketsToShow.And(SearchVals))
select new
{
Priority = ticket.TicketPriority.TicketPriorityName,
Ticket = string.Format(TicketFormat, ticket.TicketID),
AssetId = ticket.Asset.Serial,
OpenDate = ticket.CheckedInDate,
OpenFor = CalculateOpenDaysAndHours(ticket.CheckedInDate, ticket.ClosedDate),
Account = ticket.Account.Customer.Name,
Description = ticket.Description.Replace("\n", ", "),
Status = ticket.TicketStatus.TicketStatusName,
Closed = ticket.ClosedDate,
//Use Sum and the foreign relation instead of a nested query
Amount = ticket.ProductChargeItems.Where(pci => pci.Deleted == null).Sum(pci => pci.Qty * pci.Price),
Paid = ticket.Paid,
Warranty = ticket.WarrantyRepair,
AssetLocation = GetAssetLocationNameFromID(ticket.Asset.LocationID, AssLocNames)
}).Skip(totalToDisplay * page).Take(totalToDisplay);
if (SortOrder.ToLower().Contains("Asc".ToLower()))
{
query = query.OrderBy(p => p.OpenDate);
}
else
{
query = query.OrderByDescending(p => p.OpenDate);
}
I think, you can make this query simplier. Somethink like this:
public static string GetOutstandingBalanceForTicket(DataClassesDataContext context, int TicketID)
{
decimal total = 0;
var total = (from ticket in context.Tickets
join chargeItem from context.ProductChargeItems on chargeItem.ChargeID == ticket.ChargeID
where (ticket.TicketID == TicketID && chargeItem.Deleted == null)
select chargeItem).Sum(chargeItem => chargeItem.Qty * chargeItem.Price);
return total.ToString("0.##");
}
/*...*/
Amount = GetOutstandingBalanceForTicket(dataClassesDataContext, ticket.TicketID),
Now, you can inline this methos in your query.
It can contains syntax errors, because I wrote it in notepad.

LINQ Join to get latest record from 2nd table

Problem:
Their are two tables TableEmails and TableSentEmailRecords. So when ever emails are sent out, a records, such as sent time etc are stored in TableSentEmailRecords.
I want to do a LINQ query, which gets me columns of TableEmails PLUS a "SentDate" column from TableSentEmailRecords that displays the latest date that email was sent out.
I tried this:
List<CustomEmail> emails = new List<CustomEmail>();
var query = from c in db.TableEmails
join o in db.TableSentEmailRecords on c.EmailId equals o.EmailId
select new CustomEmail
{
EmailName = c.EmailName,
EmailId= c.EmailId,
EmailDescription = c.EmailDescription,
LastDateEmailSentOut = o.SentDate
};
emails = query.ToList();
but this not necessarily get the latest record of that particular email from TableSentEmailRecords table.
Any Ideas ???
You could just use a nested query instead of the join:
var query = from c in db.TableEmails
select new CustomEmail
{
EmailName = c.EmailName,
EmailId= c.EmailId,
EmailDescription= c.EmailDescription,
LastDateEmailSentOut = db.TableSentEmailRecordson
.Where(x => x.EmailId = c.EmailId)
.Max(x => x.SentDate)
};
I think GroupJoin is the correct method in this case. Using a sub query will work but it is not going to be as efficient. Sorry, I don't know the simpler query syntax that well and especially I don't know how to do group join with it. Maybe someone can translate.
db.TableEmails.GroupJoin(db.TableSendEmailRecordson,
o => o.EmailID,
i => i.EmailID,
(o, i) => new
{
EmailName = c.EmailName,
EmailId= c.EmailId,
EmailDescription= c.EmailDescription,
LastDateEmailSentOut = i.Max(x => x.SentDate)
})
To get all the details from TableSendEmailRecordson you could do something like this:
db.TableEmails.GroupJoin(db.TableSendEmailRecordson,
o => o.EmailID,
i => i.EmailID,
(o, i) => new
{
EmailName = c.EmailName,
EmailId= c.EmailId,
EmailDescription = c.EmailDescription,
LastSendEmailRecordson = i.FirstOrDefault(y => y.SentDate == i.Max(x => x.SentDate))
})
That may complain about being translated to SQL, if that is the case then you need to first get the data and then use the results in the query, eg
var emails = db.TableEmails.ToArray();
var emailSend = db.TableSendEmailRecordson.ToArray();
you can try something like this:
var query = (from c in db.TableEmails
join o in db.TableSentEmailRecordson c.EmailId equals o.EmailId
select new CustomEmail
{
EmailName = c.EmailName,
EmailId = c.EmailId,
EmailDescription = c.EmailDescription,
LastDateEmailSentOut = o.SentDate
}).OrderByDescending(c => c.LastDateEmailSentOut).ToList();

Categories

Resources