Make good LINQ query with string[] - asp.net-mvc

I have some problems with LINQ and maby someone got answers
string[] roleNames = Roles.GetRolesForUser(currentUserName);
result = context.MenuRoles.Select(mr => new MenuGenerateViewModel
{
MenuID = mr.MenuID,
MenuNazwa = mr.Menu.MenuNazwa,
MenuKolejnosc = mr.Menu.MenuKolejnosc,
MenuStyl = mr.Menu.MenuStyl,
MenuParentID = mr.Menu.MenuParentID,
MenuActive = mr.Menu.MenuActive,
MenuActionName = mr.Menu.MenuAction.MenuActionName,
MenuControlName = mr.Menu.MenuControl.MenuControlName,
RoleName = mr.Role.RoleName,
RoleID = mr.RoleID,
MenuID = mr.MenuID
})
.Where(mr => mr.MenuActive == true)
.ToList();
How to take only compare string[] roleNames and return only if match. Problem alwais is when user is in the 2 or more roles.
Tx for answers

If I understand what you are asking for, add a second condition to your Where clause:
.Where(mr => mr.MenuActive && roleNames.Contains(mr.Role.RoleName))

You would be better off switching round your Where clause and Select for the simple reason that then you will not be retrieving from the database records which are not required.
result = context.MenuRoles.Where(mr => mr.MenuActive
&& roleNames.Contains(mr.Role.RoleName))
.Select(mr => ... )
.ToList();
This will generate a sql which only selects the necessary records, instead of selecting the whole lot and then filtering it. Try it and watch SQL profiler to see the difference (useful skill in any case when using EF)

With the help of brilliant people here, reached the target.
string[] roleNames = Roles.GetRolesForUser(currentUserName);
result = context.MenuRoles
.Where(mr => mr.Menu.MenuActive && roleNames.Contains(mr.Role.RoleName))
.Select(mr => new MenuGenerateViewModel
{
MenuID = mr.MenuID,
MenuNazwa = mr.Menu.MenuNazwa,
MenuKolejnosc = mr.Menu.MenuKolejnosc,
MenuStyl = mr.Menu.MenuStyl,
MenuParentID = mr.Menu.MenuParentID,
MenuActive = mr.Menu.MenuActive,
MenuActionName = mr.Menu.MenuAction.MenuActionName,
MenuControlName = mr.Menu.MenuControl.MenuControlName,
RoleName = mr.Role.RoleName
})
.ToList();
var userresult = context.MenuUsers
.Where(mr => mr.Menu.MenuActive && mr.User.Username == currentUserName)
.Select(mr => new MenuGenerateViewModel
{
MenuID = mr.MenuID,
MenuNazwa = mr.Menu.MenuNazwa,
MenuKolejnosc = mr.Menu.MenuKolejnosc,
MenuStyl = mr.Menu.MenuStyl,
MenuParentID = mr.Menu.MenuParentID,
MenuActive = mr.Menu.MenuActive,
MenuActionName = mr.Menu.MenuAction.MenuActionName,
MenuControlName = mr.Menu.MenuControl.MenuControlName,
Username = mr.User.Username
})
.ToList();
Here, gets all the menu to which you have the right, both through group membership and assigned directly to the menu itself.
// Kick all duplicates
var noduplicates = result.Concat(userresult)
.Distinct(new RoleMenuGenerateComparer());
Because usually we do not want duplicates in the menu so we remove them. For this to work properly we need to implement IEqualityComparer (U can read about this little bit up)
public class RoleMenuGenerateComparer : IEqualityComparer<MenuGenerateViewModel>
{
public bool Equals(MenuGenerateViewModel x, MenuGenerateViewModel y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the products' properties are equal.
return x.MenuNazwa == y.MenuNazwa && x.MenuID == y.MenuID;
}
public int GetHashCode(MenuGenerateViewModel menuGenerateViewModel)
{
if (Object.ReferenceEquals(menuGenerateViewModel, null)) return 0;
int hashMenuName = menuGenerateViewModel.MenuNazwa == null ? 0 : menuGenerateViewModel.MenuNazwa.GetHashCode();
int hashMenuID = menuGenerateViewModel.MenuID == null ? 0 : menuGenerateViewModel.MenuID.GetHashCode();
return hashMenuName ^ hashMenuID;
}
}
Of course I believe that you can optimize this code, but for the moment I have something like this.
Tx all for help.

Related

how to Show deleted comments in admin

I want to put the list of deleted comments in the admin section. IsDelete capability also has a comments section. The code works fine, but when I put the where condition, the output value is zero and no comments are displayed.
public ShowCommentUsersForAdminViewModel GetRemovedCommentByAdminSearch(int pageId = 1, string filter = "")
{
//lazy load enable with IQueryable
IQueryable<BlogComment> result = _context.BlogComments
.Include(c => c.Blog)
.Include(c => c.User);
if (!string.IsNullOrEmpty(filter))
{
result = result.Where(u => u.Comment.Contains(filter) || u.User.UserName.Contains(filter) || u.Blog.BlogTitle.Contains(filter));
}
//show Item In Page
int take = 10;
int skip = (pageId - 1) * take;
ShowCommentUsersForAdminViewModel list = new ShowCommentUsersForAdminViewModel();
list.CurrentPage = pageId;
list.PageCount = (result.Count() / take) + 1;
list.BlogComments = result.Where(c => c.IsDelete).OrderBy(u => u.CreateDateComment).Skip(skip).Take(take).ToList();
return list;
}
yes I used this code
modelBuilder.Entity<ProductComment>().HasQueryFilter(b => !b.IsDelete);
Reviewed the code again, and used IgnoreQueryFilters() problem solved.
thanks Ivan Stoev

How Create Sequence number in Controller action?

I am working on a project which is an E-health patient Gateway.
I want to generate a number (int type) against a submit form from View to Controller (When phlebotomist receives the blood sample he will check the box and click on submit button). This number is the patient's blood sample number that will be generated in my controller and will be saved in the database. I am using the logic below to create the number but it always gives me zero.
Kindly let me know how I can create numbers one by one in sequence and store in database?
public ActionResult AddSampleTest(int Pid, int Tid, int Stid, string Comment ,string testDate,int DotorID)
{
int sampleNumber=1;
Random rnd = new Random();
int[] sample = new int[50000];
rnd.Next();
for (int ctr = 1; ctr <= sample.Length; ctr++)
{
sampleNumber=sample[ctr + 1];
}
string sampleno = sampleNumber.ToString();
DateTime TestDate = Convert.ToDateTime(testDate);
int Recomended_Test_DoctorID = DotorID;
// Update the Sample Status
PatientTest objpatientTest = db.PatientTests.Where(x => x.PatientID == Pid && x.Testid == Tid && x.SubTestId == Stid && x.Date==TestDate &&x.DoctorId== Recomended_Test_DoctorID).FirstOrDefault();
objpatientTest.SampleStatus = "Sample Received";
objpatientTest.SampleNumber = sampleno;
db.SaveChanges();
var name = User.Identity.Name;
int Lid = db.LabAttendantRecords.Where(x => x.Name == name).Select(x => x.User_id).FirstOrDefault();
LabTestSample obj = new LabTestSample();
obj.labtestid = Tid;
obj.PatientId = Pid;
obj.subtestid = Stid;
obj.labAtendid = Lid;
obj.date = DateTime.Now.Date;
obj.sampleReceived = true;
obj.Comment = sampleno;
db.LabTestSamples.Add(obj);
db.SaveChanges();
return RedirectToAction("TestSampleNumber", "LabAttendantDashboard", new { sampleno});
// Use This for add Result
return RedirectToAction("SubTest", "LabAttendantDashboard", new { Pid, Tid, Stid });
}
sampleNumber is always 0 because each element in sample is 0.
If you want it to be a random number you need to do something like :
Random rnd = new Random();
int sampleNumber = rnd.Next();
string sampleno = sampleNumber.ToString();
If you need to be sure that the sample number is unique, you should use a Guid :
string sampleno = Guid.NewGuid().ToString();

LINQ related error "Unable to create a constant value of type 'System.Object'. Only primitive types or enumeration types are supported in this context

I have some code that is selecting some values from my database. I have a IQueryable of requests, that contains a ICollection of rooms.
I want to get a List<ICollection<rooms>>. I have tried the following and i recieve the above error.
Any ideas??
public ActionResult _roomChecker(checkRooms JSONdata){
var rooms = db.rooms.Include(r=>r.building).Include(r=>r.facilities);
rooms = rooms.Where(r => r.capacity >= JSONdata.capacity);
if (JSONdata.type != "Any")
{
rooms = rooms.Where(r => r.roomType.Equals(JSONdata.type));
}
if (JSONdata.park != "Any")
{
rooms = rooms.Where(r => r.building.park.Equals(JSONdata.park));
}
if (JSONdata.facilities != null)
{
for (var i = 0; i < JSONdata.facilities.Length; i++)
{
rooms = rooms.Where(r => r.facilities.Any(f => f.facilityName.Equals(JSONdata.facilities[i])));
}
}
var proposedRequest = db.requests.Include(r => r.rooms);
proposedRequest = proposedRequest.Where(r=>r.booked.Equals(1));
proposedRequest = proposedRequest.Where(r => r.roundID.Equals(JSONdata.roundID));
proposedRequest = proposedRequest.Where(r => r.day.Equals(JSONdata.day));
proposedRequest = proposedRequest.Where(s => s.start < JSONdata.start + JSONdata.length && s.start + s.length > JSONdata.start);
int[] standardWeeks = new int[12] {1,2,3,4,5,6,7,8,9,10,11,12};
var containsStandard = standardWeeks.Intersect(JSONdata.weeks);
if (containsStandard.Count()!=0)
{
proposedRequest = proposedRequest.Where(r => r.weeks_request.Any(f => JSONdata.weeks.Contains(f.week)) || r.weeks.Equals(1));
}
else {
proposedRequest = proposedRequest.Where(r => r.weeks_request.Any(f => JSONdata.weeks.Contains(f.week)));
}
//ERROR OCCURS ON THIS LINE BELOW
List<ICollection<room>> bookedRooms = proposedRequest.Select(r => r.rooms).ToList();
var deptRooms = db.rooms.Include(r => r.building).Include(r => r.facilities).Where(r => r.belongsTo.Equals(JSONdata.deptCode));
roomCheckerObject suitableRooms = new roomCheckerObject();
suitableRooms.code = JSONdata.deptCode;
suitableRooms.roomNo = JSONdata.roomNo;
suitableRooms.RequestNo = JSONdata.RequestNo;
if(rooms.Count() >0){
suitableRooms.rooms = rooms.ToList();
var buildings = rooms.Select(r => r.building).Distinct();
suitableRooms.buildings = buildings.ToList();
}
if(bookedRooms.Count() >0){
suitableRooms.bookedRooms = bookedRooms;
}
if(deptRooms.Count() >0){
suitableRooms.deptRooms = deptRooms.ToList();
}
return PartialView(suitableRooms);}
It's kind of difficult to say what exactly is causing the error but I can see 3 possible culprits:
1) You're using .Equals() with a Linq to entities (L2E) query. This can cause problems, see here.
2) You say the error occurs on the line where List<ICollection<room>> is declared. On this line you call .ToList() for the first time in any of L2E statements. Only now will your L2E query be executed (see EF Query Execution) against the database meaning possibly any error (using .Equals()) in a previous L2E statement could throw the exception.
3) Does proposedRequest.Select(r => r.rooms).ToList(); really return an List<ICollection<room>>? Try using .SelectMany() (though this may have undesirable effects) or for a sanity check change List<ICollection<room>> to var to see what the query will return.

Proper return type in MVC WEB API after join table result set

This works in my web api:
public IEnumerable<Object> Get()
{
var passengerVehicle =
from vehMake in _Uow.GetRepository<VehicleMake>().Include<VehicleModel>()
join passVeh in _Uow.GetRepository<PassengerVehicle>().Include<Vehicle>()
.Include(y => y.Vehicle.VehicleModel)
.Include(y => y.Vehicle.VehicleSubModel)
.Include(y => y.Vehicle.VehicleImages)
.Include(y => y.Vehicle.VehicleLocation)
.Include(y => y.Vehicle.VehiclePrices)
on vehMake.Id equals passVeh.Vehicle.VehicleModel.FK_VehicleMakeId
select new
{
vehMake = vehMake.Name,
vehMod = passVeh.Vehicle.VehicleModel.Name,
vehSubModel = passVeh.Vehicle.VehicleSubModel.Name,
vehLocation = passVeh.Vehicle.VehicleLocation,
vehImages = passVeh.Vehicle.VehicleImages.ToList(),
vehOptions = passVeh.Vehicle.VehicleOptions.ToList(),
vehPostHistories = passVeh.Vehicle.VehiclePostHistories.ToList(),
vehStats = passVeh.Vehicle.VehicleStatistics.ToList(),
vehStatus = passVeh.Vehicle.VehicleStatus,
vehPrices = passVeh.Vehicle.VehiclePrices.ToList(),
};
return passengerVehicle;
}
I am not delighted that the return type is "object"
I thought perhaps a HttpResponse but apparently that is not correct either.
PassengerVehicle has an association with Vehicle.
Vehicle has an association with VehicleModel & VehicleSubModel.
VehicleModel has an association with VehicleMake.
Pretty much everything else are primitives or straight up collections.
Suggestions?
It would be better to use ViewModel, like:
select new VehicleSpecialViewModel
{
vehMake = vehMake.Name,
vehMod = passVeh.Vehicle.VehicleModel.Name,
vehSubModel = passVeh.Vehicle.VehicleSubModel.Name,
vehLocation = passVeh.Vehicle.VehicleLocation,
vehImages = passVeh.Vehicle.VehicleImages.ToList(),
vehOptions = passVeh.Vehicle.VehicleOptions.ToList(),
vehPostHistories = passVeh.Vehicle.VehiclePostHistories.ToList(),
vehStats = passVeh.Vehicle.VehicleStatistics.ToList(),
vehStatus = passVeh.Vehicle.VehicleStatus,
vehPrices = passVeh.Vehicle.VehiclePrices.ToList(),
};
and then your return type would be
IEnumerable<VehicleSpecialViewModel>

Is there an easier way than this to edit a table in my database?

I’m trying to update a row in a table. I found a way to make it work but I’m wondering if there is an easier or better way. Please help me with any ideas that you may have. Thanks
Here’s the code…
var courseRubics = from r in db.Rubrics where r.DepartmentID == 2 select r;
var selectedRubrics = courseRubics.Select(r => r.RubricID);
List<int> rubricsList = selectedRubrics.ToList();
foreach (var rub in courseRubics.ToList())
{
if (!String.IsNullOrEmpty(formCollection["item.Weight"]))
{
Rubric aRubic1 = db.Rubrics.Find(1);
Rubric updateRubic1 = (Rubric)aRubic1;
int rubric1 = Convert.ToInt32(totlrubric[0]);
updateRubic1.Weight = rubric1;
Rubric aRubic2 = db.Rubrics.Find(2);
Rubric updateRubic2 = (Rubric)aRubic2;
int rubric2 = Convert.ToInt32(totlrubric[1]);
updateRubic2.Weight = rubric2;
Rubric aRubic3 = db.Rubrics.Find(4);
Rubric updateRubic3 = (Rubric)aRubic3;
int rubric3 = Convert.ToInt32(totlrubric[2]);
updateRubic3.Weight = rubric3;
}
db.SaveChanges();
}
Couple of ideas / observations
Your initial set of selects could be narrowed down to (sorry for the alternate syntax)
var list = db.Rubrics.Where(r => r.DepartmentId == 2).Select(x => x.RubricId).ToList()
You iterate over foreach (var rub in courseRubics.ToList()) but don't seem to be doing anything with rub
The contents of the if... could be tightened up a little. I don't see any reason why you need to do the casting or why you can't just inline the creation of rubricX,
if (!String.IsNullOrEmpty(formCollection["item.Weight"]))
{
Rubric aRubic1 = db.Rubrics.Find(1);
aRubic1.Weight = Convert.ToInt32(totlrubric[0]);
Rubric aRubic2 = db.Rubrics.Find(2);
aRubic2.Weight = Convert.ToInt32(totlrubric[1]);
Rubric aRubic3 = db.Rubrics.Find(4);
aRubic3.Weight = Convert.ToInt32(totlrubric[2]);
}

Resources