Simple.Data Select specific columns - select

I have a call made to Simple.Data where I want to limit the columns that are being brought back. However I am hitting problems..
This works fine:
var db = Database.Open();
var questionIdRow = db.Question.FindByFriendlyId(friendlyId);
if (questionIdRow == null) return Guid.Empty;
return questionIdRow.QuestionId;
However, the following doesn't work (I get a Simple.Data.UnresolvableObjectException 'Column not found')
var db = Database.Open();
var questionIdRow = db.Question.FindByFriendlyId(friendlyId)
.Select(db.Question.QuestionId);
if (questionIdRow == null) return Guid.Empty;
return questionIdRow.QuestionId;
I was under the impression from the Simple.Data documentation that this was all that I needed to do to limit the selected columns. Note that the selection is simply selecting the same column that is referenced later on.
The actual exception is thrown on the var questionIdRow = line.
Can anybody give me some guidance?

this is a common problem, and has actually led to FindBy being deprecated before we even get to 1.0. The problem is that FindBy returns a record straight away, so you can't continue to call query methods on it.
The correct approach is to call FindAllBy and end with a First or FirstOrDefault:
var db = Database.Open();
var questionIdRow = db.Question.FindAllByFriendlyId(friendlyId)
.Select(db.Question.QuestionId)
.FirstOrDefault();
if (questionIdRow == null) return Guid.Empty;
return questionIdRow.QuestionId;

Related

Entity Framework 6: Disable Lazy Loading and specifically load included tables

Our current system is using Lazyloading by default (it is something I am going to be disabling but it can't be done right now)
For this basic query I want to return two tables, CustomerNote and Note.
This is my query
using (var newContext = new Entities(true))
{
newContext.Configuration.LazyLoadingEnabled = false;
var result = from customerNotes in newContext.CustomerNotes.Include(d=>d.Note)
join note in newContext.Notes
on customerNotes.NoteId equals note.Id
where customerNotes.CustomerId == customerId
select customerNotes;
return result.ToList();
}
My result however only contains the data in the CustomerNote table
The linked entities Customer and Note are both null, what am I doing wrong here?
I got it working with the following which is much simpler than what I've found elsewhere
Context.Configuration.LazyLoadingEnabled = false;
var result = Context.CustomerNotes.Where<CustomerNote>(d => d.CustomerId == customerId)
.Include(d=>d.Note)
.Include(d=>d.Note.User);
return result.ToList();
This returns my CustomerNote table, related Notes and related Users from the Notes.
That is callled eager loading you want to achieve.
var customerNotes = newContext.CustomerNotes.Include(t=> t.Node).ToList();
This should work, i don't really understand the keyword syntax.
If the code above doesn't work try this:
var customerNotes = newContext.CustomerNotes.Include(t=> t.Node).Select(t=> new {
Node = t.Node,
Item = t
}).ToList();

Best method to query records and get count

I am trying to query records from the DB using Entity Framework. I need to get the total count of records as well as the actual records. What is the best approach to do this
public IEnumerable<mFeedback> RetrieveAll(QueryOptions qOptions)
{
if (qOptions == null)
throw new ArgumentNullException(nameof(qOptions));
using (_db)
{
var feedback = _db.Feedbacks
.Where(f => f.isDeleted == false);
if (qOptions.GetCount)
qOptions.TotalRecordsCount = feedback.Count();
feedback = feedback.OrderBy(string.IsNullOrWhiteSpace(qOptions.Sort) ? nameof(eFeedback.CreatedDate) : qOptions.Sort)
.Skip(qOptions.Skip)
.Take(qOptions.PageSize);
return _mapper.Map<IEnumerable<eFeedback>, IEnumerable<mFeedback>>(feedback.ToList());
}
}
The current code i have is shown above. This produces 2 hits on the DB. Is there a better approach?
Thanks in advance

declare variable to store linq entity for conditional statements

I am trying to look up record using if I have the key then use Find if not use Where
private ApplicationDbContext db = new ApplicationDbContext();
public bool DeactivatePrice(int priceId = 0, string sponsorUserName = "")
{
var prices = db.BeveragePrices;
// if we have an id then find
if (priceId != 0)
{
prices = prices.Find(priceId);
}
else
{
prices = prices.Where(b => b.UserCreated == sponsorUserName);
}
if (prices != null)
{
// do something
}
return true;
I get the following error for
prices = prices.Find(priceId);
Cannot convert app.Model.BeveragePrices from system.data.entity.dbset
I am copying the pattern from this answer but something must be different.
Seems you forgot to put a predicate inside the Find function call. Also you need to do ToList on the collection. The second option is a lot more efficient. The first one gets the whole collection before selection.
Another note commented by #Alla is that the find returns a single element. So I assume another declaration had been made for 'price' in the first option I state down here.
price = prices.ToList.Find(b => b.PriceId == priceId);
Or
prices = prices.Select(b => b.PriceId == priceId);
I assume the field name is PriceId.

How to obtain a subset of records within a context using EntityFramework?

A newbie question. I am using EntityFramework 4.0. The backend database has a function that will return a subset of records based on time.
Example of working code is:
var query = from rx in context.GetRxByDate(tencounter,groupid)
select rx;
var result = context.CreateDetachedCopy(query.ToList());
return result;
I need to verify that a record does not exist in the database before inserting a new record. Before performing the "Any" filter, I would like to populate the context.Rxes with a subset of the larger backend database using the above "GetRxByDate()" function.
I do not know how to populate "Rxes" before performing any further filtering since Rxes is defined as
IQueryable<Rx> Rxes
and does not allow "Rxes =.. ". Here is what I have so far:
using (var context = new EnityFramework())
{
if (!context.Rxes.Any(c => c.Cform == rx.Cform ))
{
// Insert new record
Rx r = new Rx();
r.Trx = realtime;
context.Add(r);
context.SaveChanges();
}
}
I am fully prepared to kick myself since I am sure the answer is simple.
All help is appreciated. Thanks.
Edit:
If I do it this way, "Any" seems to return the opposite results of what is expected:
var g = context.GetRxByDate(tencounter, groupid).ToList();
if( g.Any(c => c.Cform == rx.Cform ) {....}

Better and correct way of quering with multiple condtion?

[Authorize(Roles="Admin,Manager")]
public class PermissionController : ApiController
{
[HttpGet]
public IEnumerable<permission> Get()
{
using (var mydb = new ModelContainer())
{
if(User.IsInRole("Admin")){
return mydb.permissionSet.ToList();
}
else
{
//////Work
return mydb.permissionSet.Where(x=>x.name!="Admin").ToList().Where(x=>x.name!="Coder").ToList().Where(x=>x.name!="Tester").ToList();
//////Not work
return from a in mydb.permissionSet where a.name!="Admin" && a.name!="Manager" && a.name!="Coder" && a.name != "Tester" select a;
}
}
}
}
I think there are two ways of return the correct result, the first way above will work, but seems weird and I think it will query many times. The second way seems better way, but not work.
With LINQ you are building a query. Calling ToList() on such a query will force the query to execute and return the results. Your first option will build the query and return the results. Your second option returns the query. That is the difference.
mydb.permissionSet.Where(x=>x.name!="Admin").ToList().Where(x=>x.name!="Coder").ToList().Where(x=>x.name!="Tester").ToList();
Can be broken up as this:
var qryNoAdmin = mydb.permissionSet.Where(x=>x.name!="Admin");
var permissionSetNoAdmins = qryNoAdmin.ToList();
var qryNoAdminNoCoder = permissionSetNoAdmins.Where(x=>x.name!="Coder");
var permissionSetNoAdminsNoCoders = qryNoAdminNoCoder.ToList();
var qryNoAdminNoCoderNoTester = permissionSetNoAdminsNoCoders .Where(x=>x.name!="Tester");
var permissionSetNoAdminsNoCodersNoTesters = qryNoAdminNoCoderNoTester.ToList();
return permissionSetNoAdminsNoCodersNoTesters;
If that looks inefficient to you... Yes it is. Look at #user1778606 suggestion to make it more efficient.
Now your second option only returns the query. If you call ToList() on that, the query will be executed and you get the results.
var qryNoAdminNoCoderNoTester = from a in mydb.permissionSet where a.name!="Admin" && a.name!="Manager" && a.name!="Coder" && a.name != "Tester" select a;
var permissionSetNoAdminsNoCodersNoTesters = qryNoAdminNoCoderNoTester.ToList();
return permissionSetNoAdminsNoCodersNoTesters;
Please note I didn't test this code. There might be typos.
Suggested reading: Introduction to LINQ Queries (C#)
try to put them all in the same where clause line, ie.
return mydb.permissionSet.Where(x=>x.name!="Admin" & x.name!="Coder" & x.name!="Tester").ToList();
btw, I dont think it re-queries in the way you did it first, it just filters the resulting list, but there may be a bit of overhead in recreating the list each time after the filter, ie. I think
return db.permissionSet.Where(x=>x.name!="Admin").Where(x=>x.name!="Coder").Where(x=>x.name!="Tester").ToList();
should be equally efficient to the consolidated where clause above