I want to query the table News from the database called StiriDB. There I want take all the entries that have in the Description field the word Stored in SearchTxt. I can't quite figure out what the SqlQuery method wants from me ... This is the code:
public IQueryable<News> GetProducts()
{
var _db = new SiteStiri.Models.NewsContext();
String SearchTxt = Convert.ToString(Request.QueryString["Cauta"]);
String queryTxt = "Select * from StiriDB.News where Description like '%" + SearchTxt + "%'";
IQueryable<News> query = _db.News.SqlQuery<News>(queryTxt);
if ("DesDate".Equals(DropDownSelect.SelectedItem.Value))
{
query = query.OrderByDescending(u => u.ReleaseDate);
}
if ("AsDate".Equals(DropDownSelect.SelectedItem.Value))
{
query = query.OrderBy(u => u.ReleaseDate);
}
if ("AsAlp".Equals(DropDownSelect.SelectedItem.Value))
{
query = query.OrderBy(u => u.NewsTitle);
}
if ("DesApl".Equals(DropDownSelect.SelectedItem.Value))
{
query = query.OrderByDescending(u => u.NewsTitle);
}
return query;
}
Additional details : GetProducts is called by a ListView. SearchTxt is taken with QueryString of Request because it's an URL attribute. The many ifs are for sorting the data in ascending and descending order based on certain criteria (the ifs work, I just need the SqlQuery to work as intended);
Use Linq to Entities query, something like...
public IQueryable<News> GetProducts()
{
var ctx = new SiteStiri.Models.NewsContext();
var query = from n in ctx.News
where n.Description.Contains(SearchTxt)
select n;
if ("DesDate".Equals(DropDownSelect.SelectedItem.Value))
{
query = query.OrderByDescending(u => u.ReleaseDate);
}
else if ("AsDate".Equals(DropDownSelect.SelectedItem.Value))
{
query = query.OrderBy(u => u.ReleaseDate);
}
else if ("AsAlp".Equals(DropDownSelect.SelectedItem.Value))
{
query = query.OrderBy(u => u.NewsTitle);
}
else if ("DesApl".Equals(DropDownSelect.SelectedItem.Value))
{
query = query.OrderByDescending(u => u.NewsTitle);
}
return query;
}
Related
I'm trying to make some queries using EF-Core and I have the following code
public List<Visitation> GetAllVisitations()
{
return this.hospital.Visitations
.Where(v => v.DoctorId == this.Doctor.Id)
.Select(v => new Visitation
{
Doctor = v.Doctor,
Patient = v.Patient,
Date = v.Date,
Comments = v.Comments
})
.ToList();
}
public List<Visitation> GetVisitationByPatient(int id)
{
var patient = this.GetPatientById(id);
return this.hospital.Visitations
.Where(v => v.PatientId == patient.Id)
.Select(v => new Visitation
{
Doctor = v.Doctor,
Patient = v.Patient,
Date = v.Date,
Comments = v.Comments
})
.ToList();
}
It is pretty obvious that the Select statement is the same in both methods. However I know that EF Core uses Expression<Func>, rather than Func therefore I do not know how to make an Expression, which can be used in both Select statements.
The query won't execute until you call .ToList(). So you may take the partial query up to the .Where() and pass it to a function that adds the Select() portion.
Something like this:
public List<Visitation> GetAllVisitations()
{
var query = this.hospital.Visitations
.Where(v => v.DoctorId == this.Doctor.Id);
return this.addTransformation(query)
.ToList();
}
public List<Visitation> GetVisitationByPatient(int id)
{
var patient = this.GetPatientById(id);
var query = this.hospital.Visitations
.Where(v => v.PatientId == patient.Id)
return this.addTransformation(query)
.ToList();
}
public IQueriable<Visitation> AddTransformation(IQueriable<Visitation> query)
{
return query.Select(v => new Visitation
{
Doctor = v.Doctor,
Patient = v.Patient,
Date = v.Date,
Comments = v.Comments
});
}
I have a foreach with an ordebydescending(), but in one case I need to use an orderby() instead. Depending on the value of articleType how can I use an inline condition inside the foreach to allow this to happen.
This is the condition I need to build into to determine the use of orderbydescending or orderby
if (articleType == BusinessLogic.ArticleType.Webinar)
This is the full function
public static List<Article> GetArticles(BusinessLogic.ArticleType articleType, long languageID)
{
List<Article> articles = new List<Article>();
using (var db = new DatabaseConnection())
{
foreach (var record in db
.GetArticles(BusinessLogic.SystemComponentID, (int) articleType, languageID)
.OrderByDescending(c => c.Date_Time))
{
#region articleTextLanguageID
long articleTextLanguageID = GetArticleTextLanguageID(record.ID, languageID);
string previewImageName = GetArticle(record.ID, articleTextLanguageID).PreviewImageName;
#endregion
Article article = new Article()
{
ID = record.ID,
Title = record.Title,
Summary = record.Summary,
PreviewImageName = previewImageName,
Date = record.Date_Time,
ArticleTextLanguageID = articleTextLanguageID
};
articles.Add(article);
}
}
return articles;
}
Was thinking something along these lines, but its not working
foreach (var record in db
.GetArticles(BusinessLogic.SystemComponentID, (int)articleType, languageID)
.Where(articleType == BusinessLogic.ArticleType.Webinar.ToString()?.OrderByDescending(c => c.Date_Time)) : .OrderBy(c => c.Date_Time)))
The way to do this would be to construct the query in pieces. For example:
var query = db.GetArticles(BusinessLogic.SystemComponentID, (int)articleType, languageID);
if(articleType == BusinessLogic.ArticleType.Webinar)
{
query = query.OrderByDescending(c => c.Date_Time);
}
else
{
query = query.OrderBy(c => c.Date_Time);
}
foreach(var record in query)
{
// process
}
If you required additional sorting, you'd need an extra variable typed as IOrderedEnumerable/IOrderedQueryable (depending on what GetArticles returns) as an intermediate to chain ThenBy/ThemByDescending:
var source = db.GetArticles(BusinessLogic.SystemComponentID, (int)articleType, languageID);
IOrderedEnumerable<Article> query;
if(articleType == BusinessLogic.ArticleType.Webinar)
{
query = source.OrderByDescending(c => c.Date_Time);
}
else
{
query = source.OrderBy(c => c.Date_Time);
}
if(somethingElse)
{
query = query.ThenBy(c => c.OtherProperty);
}
foreach(var record in query)
{
// process
}
Based on your comment below, as notes above the second example would look more like the following (this means that db.GetArticles returns an IQueryable<Article> and not an IEnumerable<Article>):
var source = db.GetArticles(BusinessLogic.SystemComponentID, (int)articleType, languageID);
IOrderedQueryable<Article> query;
if(articleType == BusinessLogic.ArticleType.Webinar)
{
query = source.OrderByDescending(c => c.Date_Time);
}
else
{
query = source.OrderBy(c => c.Date_Time);
}
if(somethingElse)
query = query.ThenBy(c => c.OtherProperty);
foreach(var record in query)
{
// process
}
You could also shorten it to the following:
var source = db.GetArticles(BusinessLogic.SystemComponentID, (int)articleType, languageID);
var query = articleType == BusinessLogic.ArticleType.Webinar
? source.OrderByDescending(c => c.Date_Time)
: source.OrderBy(c => c.Date_Time);
if(somethingElse)
query = query.ThenBy(c => c.OtherProperty);
foreach(var record in query)
{
// process
}
I want to load a list of objects from db using Entity Framework 6 and Eager loading. But Entity Framework instead uses lazy loading. I've used SQL profiler and the queries are executed when a property referring to the child entities is accessed.
By using the 'Include' you suppose to load related entities in one go but it's not happening. My Code is presented below:
using (var flightsPricingRulesContext = new FlightsPricingRulesDbContext())
{
flightsPricingRulesContext.Configuration.ValidateOnSaveEnabled = false;
flightsPricingRulesContext.Configuration.AutoDetectChangesEnabled = false;
var filter = PredicateBuilder.True<FlightsPricingRulesDataAccess.Models.ServiceFee>();
if (!String.IsNullOrEmpty(selectedMarketId))
{
var selectedMarket = Int32.Parse(selectedMarketId);
filter = filter.And(sf => sf.MarketId == selectedMarket);
}
if (!String.IsNullOrEmpty(selectedApplicationTypeId))
{
var selectedAppplicationType = Int32.Parse(selectedApplicationTypeId);
filter = filter.And(sf => sf.ApplicationType == selectedAppplicationType);
}
var Query =
from P in flightsPricingRulesContext.ServiceFee.AsExpandable().Where(filter)select P;
switch (orderby)
{
case null:
case "":
case "Id":
Query = String.IsNullOrEmpty(orderbydirection) || orderbydirection == "ASC"
?Query.OrderBy(p => p.Id): Query.OrderByDescending(p => p.Id);
break;
case "market":
Query = String.IsNullOrEmpty(orderbydirection) || orderbydirection == "ASC"
? Query.OrderBy(p => p.MarketId)
: Query.OrderByDescending(p => p.MarketId);
break;
}
var takeitems = 10 ;
var skipitems = (Int32.Parse(page) - 1) * 10);
//BY USING INCLUDE EAGER LOADING IS ENABLED
Query = Query.Skip(skipitems).Take(takeitems).
Include(sf => sf.ServiceFeeZone.Select(sfz => sfz.Zone)).
Include(sf => sf.ServiceFeeCarrier).
Include(sf => sf.ServiceFeeClassOfService).
Include(sf => sf.ServiceFeeDate).
Include(sf => sf.ServiceFeeMarkUpAssignment).
Include(sf => sf.ServiceFeeAssignment);
var results = Query.ToList();//HERE A COMPLETE QUERY SHOULD BE
//SENT TO THE DB FOR RETRIEVING ENTITES INCLUDING THEIR CHILDREN
var totalresults = flightsPricingRulesContext.ServiceFee.AsExpandable().Count(filter);
var pagedservicefees = new PagedServiceFee();
pagedservicefees.totalitems = totalresults.ToString();
pagedservicefees.servicefees = new List<FlightsPricingRules.Models.ServiceFee>();
foreach (var servicefeedto in results)
{
var servicefee = new FlightsPricingRules.Models.ServiceFee();
servicefee.id = servicefeedto.Id.ToString();
servicefee.marketId = servicefeedto.MarketId.ToString();
//.....
//SOME MORE PROPERTIES
//
//CHILD ENTITIES
//Zones
servicefee.zones = new List<Zone>();
//HERE AN ADDITIONAL QUERY IS MADE TO LOAD THE CHILD ENTITIES-WHY?
foreach (var zonedto in servicefeedto.ServiceFeeZone)
{
var zone = new Zone();
zone.id = zonedto.ZoneId.ToString();
zone.name = zonedto.Zone.Name;
servicefee.zones.Add(zone);
}
//Carriers
servicefee.carriers = new List<Carr>();
//ALSO HERE AND ADDITIONAL QUERY IS MADE
foreach (var carrierdto in servicefeedto.ServiceFeeCarrier)
{
var carrier = new Carr();
carrier.id = carrierdto.AirlineId.ToString();
servicefee.carriers.Add(carrier);
}
pagedservicefees.servicefees.Add(servicefee);
}
//.......
//SOME MORE CHILD ENTITIES
//
return Json(pagedservicefees, JsonRequestBehavior.DenyGet);
}
OK, I figured it out. It turns out that it does matter where you place the Include statements. I placed the Include statements before the .AsExpandable() and after the parent entity and now eager loading is performed. I can also verify with SQL profiler, the query contains all the necessary joins and it's executed really fast. The correct query is now:
var Query = from P in flightsPricingRulesContext.ServiceFee
.Include(sf => sf.ServiceFeeCarrier)
.Include(sf=>sf.ServiceFeeAssignment)
.Include(sf => sf.ServiceFeeClassOfService)
.Include(sf => sf.ServiceFeeDate)
.Include(sf => sf.ServiceFeeMarkUpAssignment)
.Include(sf => sf.ServiceFeeZone.Select(zo => zo.Zone))
.AsExpandable().Where(filter) select P;
Posting the answer in case someone encounters a same scenario.
I'm trying to query a db set, but I can't seem to access the data when I get the results. Here is the code I've tried.
Query #1:
public List<CustomerMain> testing()
{
var context = new CustomerEntities();
var query = context.CustomerMains
.Where(p=> p.FirstName == "Thor")
.Select(p => new CustomerMain {FirstName=p.FirstName,LastName =p.LastName}).ToList();
return query;
}
Query #2:
public IQueryable<CustomerMain> testing()
{
var context = new CustomerEntities();
var query = context.CustomerMains
.Where(p=> p.FirstName == "Thor")
.Select(p => new CustomerMain {FirstName=p.FirstName,LastName =p.LastName});
return query;
}
CustomerMain is my DbSet, If I run either of those and assign the method to a var variable, it gives me no options to grab the FirstName or LastName from the variable. I found I can do it if I convert it to a CustomerMain, but shouldn't the return query be in a CustomerMain type already?
it gives me no options to grab the FirstName or LastName from the variable
Because the method returns a collection or queryable, not a single entity. You need to iterate or select records:
var customers = testing();
foreach (CustomerMain customer in customers)
{
// access customer.FirstName
}
Or:
var customers = testing();
var oneCustomer = customers.FirstOrDefault(c => c.FirstName == "Thor");
// access oneCustomer.FirstName
Or, if you want the method to return one record (or null if none found):
public CustomerMain FindOne(string firstName)
{
using (var context = new CustomerEntities())
{
var query = context.CustomerMains.Where(p => p.FirstName == firstName);
return query.FirstOrDefault();
}
}
I have a bunch of Linq to Entity methods that had the same select statement, so I thought I would be clever and separate that out into it's own method to reduce redundancy... but when i attempted to run the code, i got the following error...
this method cannot be translated into
a store expression
Here is the method i created...
public User GetUser(DbUser user, long uid)
{
return new User
{
Uid = user.uid,
FirstName = user.first_name,
LastName = user.last_name
};
}
And am calling in a method like this...
public User GetUser(long uid)
{
using (var entities = new myEntities()) {
return
entities.DbUsers.Where( x => x.uid == uid && x.account_status == ( short )AccountStatus.Active ).
Select( x => GetUser( x, uid ) ).FirstOrDefault( );
}
}
UPDATE: here is the code that works inline
public User GetUser(long uid, long uid_user)
{
using (var entities = new myEntities())
{
var q = from u in entities.DbUsers
where u.uid == uid_user
select new User
{
Uid = u.uid,
FirstName = u.first_name,
LastName = u.last_name,
BigPicUrl = u.pic_big,
Birthday = u.birthday,
SmallPicUrl = u.pic_small,
SquarePicUrl = u.pic_square,
Locale = u.locale.Trim(),
IsFavorite = u.FavoriteFriends1.Any(x => x.uid == uid),
FavoriteFriendCount = u.FavoriteFriends.Count,
LastWishlistUpdate = u.WishListItems.OrderByDescending(x => x.added).FirstOrDefault().added,
Sex = (UserSex)u.sex
};
var user = q.FirstOrDefault();
user.DaysUntilBirthday = user.Birthday.DaysUntilBirthday();
return user;
}
}
The error is spot on, you can't translate that into a T-SQL (or P-SQL) query.
You need to make sure you've executed the query before you attempt to hydrate it into some other type.
Keep it simple, use an extension method. That's what they are there for.
public static User ToUserEntity(this DbUser user)
{
return new User
{
Uid = user.uid,
FirstName = user.first_name,
LastName = user.last_name
};
}
Then in your DAL:
public User GetUser(long uid)
{
User dbUser;
using (var entities = new myEntities())
{
dbUser = entities.DbUsers
.Where( x => x.uid == uid && x.account_status == (short)AccountStatus.Active )
.FirstOrDefault(); // query executed against DB
}
return dbUser.ToUserEntity();
}
See how i hydrate the POCO into an object after the context has been disposed? This way, you ensure EF has finished it's expression work before you attempt to hydrate into a custom object.
Also i dont know why you're passing uid to that method, it's not even being used.
On a further note, you shouldn't need to do this kind of thing (project EF POCO's into your own objects).
If you do, it's a good case for custom POCO's (map the tables straight into your custom POCO's, don't use the Code Generation).
This expression will work to give the desired result (somewhat) I still havent figured out how to pass in additional variables in teh select statements...
..... .Select(GetUser).FirstOrDefault()
static readonly Expression<Func<DbUser, User>> GetUser = (g) => new User {
Uid = g.uid,
FirstName = g.first_name,
LastName = g.last_name,
BigPicUrl = g.pic_big,
Birthday = g.birthday,
SmallPicUrl = g.pic_small,
SquarePicUrl = g.pic_square,
Locale = g.locale.Trim(),
//IsFavorite = g.FavoriteFriends1.Any(x=>x.uid==uid),
FavoriteFriendCount = g.FavoriteFriends.Count,
LastWishlistUpdate = g.WishListItems.OrderByDescending( x=>x.added ).FirstOrDefault().added
};
You can't do this because the getUser method cannot be converted to any TSQL statement.
if you return your DBUser first and then use it as the first parameter of the GetUser method then you are forcing it to execute and once you have you DBUser you can pass it to GetUser
Maybe you can try this:
public User GetUser(long uid)
{
using (var entities = new myEntities())
{
return GetUser(
entities.DbUsers
.Where( x => x.uid == uid && x.account_status == (short)AccountStatus.Active )
.FirstOrDefault(),
uid);
}
}
EDIT
Since you are saying it still fails could it be beacuse of the enum??
public User GetUser(long uid)
{
using (var entities = new myEntities())
{
short status = (short)AccountStatus.Active;
return GetUser(
entities.DbUsers
.Where( x => x.uid == uid && x.account_status == status )
.FirstOrDefault(),
uid);
}
}