I'am trying to search employees by using async and await with button function, but my code doesn't work as my expect and get error like "requires a receiver of type 'IQueryable'". How should I do if I want to use async await in windows form.
Here is my code: Thank you in advance!
private async void btnSearch_Click(object sender, EventArgs e)
{
using(db)
{
var employees = db.Analys
.Where(x => x.Status == true)
.Select(a => new { a.UserId, a.FirstName, a.LastName, a.DOB, a.Department, a.DepartmentId })
.AsEnumerable()
.Select(b => new {
UserId = b.UserId,
FirstName = b.FirstName,
LastName = b.LastName,
Age = CalculateAge(b.DOB.ToString()),
Department = b.Department.DepartmenName,
});
var data = await employees.ToListAsync();
if (data!= null)
{
dgvEmployees.DataSource = data;
}
}
}
Can you please add full error text? But from the code you've already provided I assume you are using Entity Framework to access your DB, so AsEnumerable() should already have materialized the data fetching it from db. I would say that you don't need it here, and first Select clause too. Try something like this:
var employees = await db.Analys
.Where(x => x.Status == true)
.Select(b => new {
UserId = b.UserId,
FirstName = b.FirstName,
LastName = b.LastName,
Age = CalculateAge(b.DOB.ToString()),
Department = b.Department.DepartmenName,
})
.ToListAsync();
Also the null check should not be needed here, cause EF should return empty collection.
Related
When running this code:
public async Task<IActionResult> AddMessage()
{
int distid = ViewBag.DISTRIBUTORID;
ViewBag.PageName = "Send Message";
int id = Convert.ToByte(ViewBag.ID);
ViewBag.UserId = id;
var messages = await _companyContext.MESAJLAR.Where(p => p.SENDERID == id || p.SENTID == id).OrderBy(p => p.DATE).GroupBy(p => p.SPECIALID).Select(p => p.Last()).ToListAsync();
var ids1 = messages.Select(p => p.SENDERID).ToArray();
var ids2 = messages.Select(p => p.SENTID ).ToArray();
var users= await _userDatabaseContext.user.Where(p => p.DISTID == distid && p.ID != id && !ids1.Contains(p.ID) && !ids2.Contains(p.ID)).ToListAsync();
return View(new AddMessageViewModel
{
USERS= users
});
}
I get the following error:
Queries performing 'Last' operation must have a deterministic sort order.Rewrite the query to apply an 'OrderBy' operation on the sequence before calling 'Last'.
I'm getting it at the line that starts with var messages = ...
The Problem with your query is, that you are trying to select .Last() without ordering your data first.
Right now you are ordering your data, then group it and after that you try to select 'Last()'.
You have to order the grouped data to use '.Last()'.
var messages = await _companyContext.MESAJLAR.Where(p => p.SENDERID == id || p.SENTID == id).OrderBy(p => p.DATE).GroupBy(p => p.SPECIALID).OrderBy(p => p.XXXXX).Select(p => p.Last()).ToListAsync();
And your first order would probably be not needed anymore.
I want to sort the data based on CreatedUtc time. I have tried to use Reverse function, it seems to work out but still looking for some alternate option.
var result = _participantRepo.AsQueryable().Where(x => x.Id == ParticipantId).SelectMany(x =>
x.Relations).ToList().Where(x => x.UserId != AppUserId).Select(r => new RelationVM
{
IsOwner = r.UserId == participant.CreatedByUserId,
FirstName = r.FirstName,
LastName = r.LastName,
Email = r.Email,
UserId = r.UserId,
RelationType = r.RelationType,
Role = r.Role,
IsAccepted = r.IsAccepted,
AvatarUrl = r.AvatarUrl,
CreatedUtc = r.CreatedUtc
}).Reverse().ToList();
There are 2 things you need to concern:
You can sort the elements of a sequence by using OrderBy
You should not .ToList() when you have not done, So you might to read LINQ deferred (or immediate?) execution to have a better understanding.
As a result, your query should look like this
var result = _participantRepo.AsQueryable().Where(x => x.Id == ParticipantId).SelectMany(x =>
x.Relations).Where(x => x.UserId != AppUserId).Select(r => new RelationVM
{
IsOwner = r.UserId == participant.CreatedByUserId,
FirstName = r.FirstName,
LastName = r.LastName,
Email = r.Email,
UserId = r.UserId,
RelationType = r.RelationType,
Role = r.Role,
IsAccepted = r.IsAccepted,
AvatarUrl = r.AvatarUrl,
CreatedUtc = r.CreatedUtc
}).Reverse().OrderBy(g => g.CreatedUtc).ToList();
How about .OrderBy(g => g.CreatedUtc) ?
I used ADO.NET Entity Database Model (auto-generated) for my angularJS application using database model shown below:
Currently I am using this code to get all data from Contact table:
ContactsEntities db = new ContactsEntities();
public JsonResult GetAll()
{
return Json(db.Contacts.ToList(), JsonRequestBehavior.AllowGet);
}
What I want to achieve is to get all data from database. Is there way to get all data in single "query" or do I need to call
return Json(db.{MODEL NAME}.ToList(), JsonRequestBehavior.AllowGet);
for each model(table) to get data? Is there better solution to get all data from database or do I need to call each model separately?
You should try something like this:
var data = (from c in db.Contacts
from e in db.Emails.Where(x => x.id == c.id_email).DefaultIfEmpty()
from p in db.Phones.Where(x => x.id == c.id_phone).DefaultIfEmpty()
from t in db.Tags.Where(x => x.id == c.id_tag).DefaultIfEmpty()
select new
{
id = c.id,
phone = p.number,
email = e.email1,
tag = t.tag1,
firstname = c.firstname,
lastname = c.lastname,
address = c.address,
city = c.city,
bookmarked = c.bookmarked,
notes = c.notes
}).ToList();
return Json(data, JsonRequestBehavior.AllowGet);
Or if you want to prepare yourself for the future, when you add multiple properties to the Contact/Email/... classes and don't want to change your code:
var data = (from c in db.Contacts
from e in db.Emails.Where(x => x.id == c.id_email).DefaultIfEmpty()
from p in db.Phones.Where(x => x.id == c.id_phone).DefaultIfEmpty()
from t in db.Tags.Where(x => x.id == c.id_tag).DefaultIfEmpty()
select new
{
Contact = c,
Email = e,
Phone = p,
Tag = t
}).ToList();
I have the following database code:
static IEnumerable<dynamic> GetData(bool withchildren) {
using (var model = new testEntities()) {
var res = default(IQueryable<dynamic>);
if (withchildren) {
res = model.UserSet
.Where(u => u.name != "")
.Select(u => new {
Name = u.name,
Email = u.email,
Groups = u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
})
});
} else {
res = model.UserSet
.Where(u => u.name != "")
.Select(u => new {
Name = u.name,
Email = u.email
});
}
return res.ToList()
}
}
I would like to shrink the code and write it like this:
static IEnumerable<dynamic> GetData(bool withchildren) {
using (var model = new testEntities()) {
var res = default(IQueryable<dynamic>);
res = model.UserSet
.Where(u => u.name != "")
.Select(u => {
dynamic item = new {
Name = u.name,
Email = u.email
};
if(withchildren) {
item.Groups = u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
});
}
return item;
});
return res.ToList();
}
}
But Visual Studio complains, that it cannot convert the lambda expression into an expression tree.
My question is, is there a way to accomplish that with the Entity Framework and Linq? I really wouldn't want to use ADO.net directly.
Maybe there is even a better version to shrink it, than the code that I imagine.
Here is a related question with Linq-To-Objects.
EDIT
Before someone asks, I use dynamic in the example code to make it a bit easier and faster.
EDIT 2
My goal with this approach is, to only query the fields I need to improve performance. Check http://www.progware.org/Blog/post/Slow-Performance-Is-it-the-Entity-Framework-or-you.aspx.
At the moment we use something like
static IEnumerable<dynamic> GetData(bool withchildren) {
using (var model = new testEntities()) {
var res = default(IQueryable<dynamic>);
res = model.UserSet
.Where(u => u.name != "")
.ToList();
return res;
}
}
And the performance is, according to Glimpse, horrible.
EDIT 3
Short side note, I made up some quick and dirty code. That is, why the foreach at the end was not needed. The actual code is not available at the moment.
Is there any reason you couldn't use:
res = model.UserSet
.Where(u => u.name != "")
.Select(u => new {
Name = u.name,
Email = u.email,
Groups = withchildren
? u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
})
: null;
})
};
or perhaps:
res = model.UserSet
.Where(u => u.name != "")
.ToList() // ToList() here to enumerate the items
.Select(u => {
dynamic item = new {
Name = u.name,
Email = u.email
};
if(withchildren) {
item.Groups = u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
});
}
return item;
});
One approach that would allow you to eliminate some code would be:
var res = model.UserSet.Where(u => u.name != "");
if (withchildren) {
res = res.Select(u => new {
Name = u.name,
Email = u.email,
Groups = u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
})
});
} else {
res = res.Select(u => new {
Name = u.name,
Email = u.email
});
}
One of the most requested by community feature is support of multi-line expressions in EF,
however so far, you can use only conditional operator "?:" as well as wrap result in
one common type, so both your results will have to have "Groups" field.
Also there are an extensions to linq-providers such as https://www.nuget.org/packages/LinqKit/ ,
however they are based on own conventions so any developer should study it in depth before
taking advance in applying and supporting code written upon that extensions.
I have the following as part of my entity framework class:-
public CustomerDetails GetCustomer(int id) {
var customerDetails = entities.AccountDefinitions
.Where(a => a.ORG_ID == id)
.Select(cd => new CustomerDetails
{
AD = cd,
SD = cd.SDOrganization,
AA = cd.SDOrganization.AaaPostalAddresses,
SN = cd.SiteDefinitions,
Ar = cd.SiteDefinitions.SelectMany(a => a.DepartmentDefinitions.SelectMany(a2 => a2.SDUsers.Select(a3 => a3.AaaUser)))
})
.SingleOrDefault();
return customerDetails;
}
Inside the inner .Select I have five assignments operations, but since some assignments depend upon the other so how I can write something such as:-
Ar = SN.SelectMany(…….)
So in this way I will only query the database only one time to retrieve the cd.SiteDefenitions??
One option would be to do it like this:
var customerDetails = entities.AccountDefinitions
.Where(a => a.ORG_ID == id)
.Select(cd => new CustomerDetails
{
AD = cd,
SD = cd.SDOrganization,
AA = cd.SDOrganization.AaaPostalAddresses,
SN = cd.SiteDefinitions
})
.SingleOrDefault();
if (customerDetails != null)
{
customerDetails.Ar = customerDetails.SN...
}
return customerDetails;
I know it may not be quite what you were looking for, but you're not going to be able to get at the SN property during the parameterless constructor operation like that (AFAIK).