Loop that return AND value in MVC - asp.net-mvc

I have created this loop in MVC:
//this identify my user
string tmpUser = System.Web.HttpContext.Current.User.Identity.Name;
//this find user in database and compare his username with Identity name and returns userID
using (var dbUs = new userDbEntities())
{
var whoisloged = (from user in dbUs.UsersTables
where user.username == tmpUser
select user.userID).FirstOrDefault();
//get all destinations for user userid
var list1 = dbUs.CustomerTables.Where(m => m.UserId == whoisloged).Select(m => m.Customer);
var list2 = dbUs.CustomTypes.Where(m => list1.Contains(m.Id_NewCustomerType)).Select(m => m.CustomerType);
//this is LOOP that must return my values
foreach (var customer in list2)
{
string test = customer;
return new SolrQuery(test);
}
Now Problem is in my LOOP foreach... Why is returning only first value? no matter that I have more data in the database.
My result sholud be something like this:
e.g. user Somebody login in app. He/She have in database saved his/her roles (CustomerTable in code) that are e.g. A, B and C, so loop should return me something like this:
return new SolrQuery(A) + return new SolrQuery(B) + return new SolrQuery(C); // + is refer as AND
Realy thanks for help and any ideas...

The first return leaves not only the foreach, but the whole function (as return is intended to do). If you want to do more than one query in the loop, you have to collect the results and return them afterwards...
string result ="";
foreach (var customer in list2)
{
result = result + new SolrQuery(customer);
}
return result;
should do the trick.

The trouble is that:-
return new SolrQuery(test);
returns a single SolrQuery and then exits the function breaking out of your loop.
What you probably want to do is modify your method signature:-
public SolrQuery MyMethod(...)
to:-
public IEnumerable<SolrQuery> MyMethod(...)
to indicate that you want the method to return a sequence of items, rather than a single one.
Then you can use the yield keyword to create the sequence:-
foreach (var customer in list2)
{
yield return new SolrQuery(customer);
}
Or, better, you can just return the result of your LINQ query (which is already a sequence). Replace:-
var list2 = dbUs.CustomTypes.Where(m => list1.Contains(m.Id_NewCustomerType))
.Select(m => m.CustomerType);
with:-
return dbUs.CustomTypes.Where(x => list1.Contains(x.Id_NewCustomerType))
.Select(x => new SolrQuery(x.CustomerType))
.ToList();
and then remove everything after.

I have solve it:
List<string> result = new List<string>();
foreach (var customer in seznam2)
{
result.Add(customer);
}
SolrQueryInList queryInList = new SolrQueryInList("destination", result);
return queryInList;

Related

Update all column records in mvc5 using linq query

I want to update all the records of a particular column in MVC5 using linq query
var PriceRecord = db.tblPurchasePrices.Where(z => z.ID == id).SingleOrDefault();
var PurchasePriceList = db.tblPurchasePrices.Where(z => z.SizeID == PriceRecord.SizeID && z.ProductID == PriceRecord.ProductID && z.CategoryID == PriceRecord.CategoryID).ToList();
foreach (var item in PurchasePriceList)
{
item.IsActive = false;
db.SaveChanges();
}
i do not want to use foreach loop to update record one by one and save changes. i want all values in a particular column to update in one go.
Try this code, you can save all changes in one trip to DB:
foreach (var item in PurchasePriceList)
{
item.IsActive = false;
db.Entry(item).State = EntityState.Modified;
}
db.SaveChanges();
or another syntax:
foreach (var item in PurchasePriceList)
{
item.IsActive = false;
db.Entry(item).Property(i=> i.IsActive).IsModified = true;
}
db.SaveChanges();
Another way to update bulk data that maybe faster (maybe not) is to create a stored procedure with PriceRecord parameters and execute like this :
db.Database.ExecuteSqlCommand("stored_procedure_name #params", params);

To remove an item in List

I am trying to remove an item in my gcNumber but it is not getting removed. Below is my code. i know i am doing some silly thing but don't know where :(
var gcn=gcNumber.ToList();
foreach (var selectGc in gcn)
{
var countToRemove = _uow.GetRepository<TripSheetGcDetail>().GetAll().Where(x => x.FkGcId == selectGc.Id && x.IsActive == true).Select(y => y);
if(countToRemove .Count()>0)
{
gcNumber.ToList().Remove(selectGc);
}
else
{
}
}
return gcNumber.ToList();
if my CountToRemove.count()>0 then i want to remove that item in my gcNumber list. Kindly help where i am doing wrong.
gcNumber.ToList().Remove(selectGc);
This line creates a new list, which you remove stuff from, then since you don't do anything else (like assign the list any where) throws the modified list away.
I'm guessing what you want to do instead is something like:
gcn.Remove(selectGc);
You also want to modify your foreach so that it isn't looping over something that is getting modified.
foreach(var selectGg in gcNumber)
This will loop over the original thing, allowing you to modify the copy.
And you'll probably want to return gcn, as your return statement just creates another new list based on gcNumber which hasn't been modified.
In summary: .ToList() creates a new list every time, so modifying that list won't do anything to the original.
instead of gcNumber.ToList().Remove(selectGc); just do gcNumber.Remove(selectGc);
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public class MyClass
{
public string Name {get; set;}
}
public static void Main()
{
var list = new List<MyClass>();
list.Add(new MyClass() {Name = "aaa"});
list.Add(new MyClass() {Name = "bbb"});
list.Add(new MyClass() {Name = "ccc"});
list.Add(new MyClass() {Name = "ddd"});
var indexesToRemove = new List<int>();
foreach(var item in list)
{
if(item.Name == "aaa")
indexesToRemove.Add(list.IndexOf(item));
}
foreach (var num in indexesToRemove)
list.RemoveAt(num);
Console.WriteLine(list.First().Name);
}
}
Maby it is not the best way to remove items from list but it's clear. You can't remove items form list which is enumerating.

Best Way to Update only modified fields with Entity Framework

Currently I am doing like this:
For Example:
public update(Person model)
{
// Here model is model return from form on post
var oldobj = db.Person.where(x=>x.ID = model.ID).SingleOrDefault();
db.Entry(oldobj).CurrentValues.SetValues(model);
}
It works, but for example,
I have 50 columns in my table but I displayed only 25 fields in my form (I need to partially update my table, with remaining 25 column retain same old value)
I know it can be achieve by "mapping columns one by one" or by creating "hidden fields for those remaining 25 columns".
Just wondering is there any elegant way to do this with less effort and optimal performance?
This is a very good question. By default I have found that as long as change tracking is enabled (it is by default unless you turn it off), Entity Framework will do a good job of applying to the database only what you ask it to change.
So if you only change 1 field against the object and then call SaveChanges(), EF will only update that 1 field when you call SaveChanges().
The problem here is that when you map a view model into an entity object, all of the values get overwritten. Here is my way of handling this:
In this example, you have a single entity called Person:
Person
======
Id - int
FirstName - varchar
Surname - varchar
Dob - smalldatetime
Now let's say we want to create a view model which will only update Dob, and leave all other fields exactly how they are, here is how I do that.
First, create a view model:
public class PersonDobVm
{
public int Id { get; set; }
public DateTime Dob { get; set; }
public void MapToModel(Person p)
{
p.Dob = Dob;
}
}
Now write the code roughly as follows (you'll have to alter it to match your context name etc):
DataContext db = new DataContext();
Person p = db.People.FirstOrDefault();
// you would have this posted in, but we are creating it here just for illustration
var vm = new PersonDobVm
{
Id = p.Id, // the Id you want to update
Dob = new DateTime(2015, 1, 1) // the new DOB for that row
};
vm.MapToModel(p);
db.SaveChanges();
The MapToModel method could be even more complicated and do all kinds of additional checks before assigning the view model fields to the entity object.
Anyway, the result when SaveChanges is called is the following SQL:
exec sp_executesql N'UPDATE [dbo].[Person]
SET [Dob] = #0
WHERE ([Id] = #1)
',N'#0 datetime2(7),#1 int',#0='2015-01-01 00:00:00',#1=1
So you can clearly see, Entity Framework has not attempted to update any other fields - just the Dob field.
I know in your example you want to avoid coding each assignment by hand, but I think this is the best way. You tuck it all away in your VM so it does not litter your main code, and this way you can cater for specific needs (i.e. composite types in there, data validation, etc). The other option is to use an AutoMapper, but I do not think they are safe. If you use an AutoMapper and spelt "Dob" as "Doob" in your VM, it would not map "Doob" to "Dob", nor would it tell you about it! It would fail silently, the user would think everything was ok, but the change would not be saved.
Whereas if you spelt "Dob" as "Doob" in your VM, the compiler will alert you that the MapToModel() is referencing "Dob" but you only have a property in your VM called "Doob".
I hope this helps you.
I swear by EntityFramework.Extended. Nuget Link
It lets you write:
db.Person
.Where(x => x.ID == model.ID)
.Update(p => new Person()
{
Name = newName,
EditCount = p.EditCount+1
});
Which is very clearly translated into SQL.
Please try this way
public update(Person model)
{
// Here model is model return from form on post
var oldobj = db.Person.where(x=>x.ID = model.ID).SingleOrDefault();
// Newly Inserted Code
var UpdatedObj = (Person) Entity.CheckUpdateObject(oldobj, model);
db.Entry(oldobj).CurrentValues.SetValues(UpdatedObj);
}
public static object CheckUpdateObject(object originalObj, object updateObj)
{
foreach (var property in updateObj.GetType().GetProperties())
{
if (property.GetValue(updateObj, null) == null)
{
property.SetValue(updateObj,originalObj.GetType().GetProperty(property.Name)
.GetValue(originalObj, null));
}
}
return updateObj;
}
I have solved my Issue by using FormCollection to list out used element in form, and only change those columns in database.
I have provided my code sample below; Great if it can help someone else
// Here
// collection = FormCollection from Post
// model = View Model for Person
var result = db.Person.Where(x => x.ID == model.ID).SingleOrDefault();
if (result != null)
{
List<string> formcollist = new List<string>();
foreach (var key in collection.ToArray<string>())
{
// Here apply your filter code to remove system properties if any
formcollist.Add(key);
}
foreach (var prop in result.GetType().GetProperties())
{
if( formcollist.Contains(prop.Name))
{
prop.SetValue(result, model.GetType().GetProperty(prop.Name).GetValue(model, null));
}
}
db.SaveChanges();
}
I still didn't find a nice solution for my problem, so I created a work around. When loading the Entity, I directly make a copy of it and name it entityInit. When saving the Entity, I compare the both to see, what really was changed. All the unchanged Properties, I set to unchanged and fill them with the Database-Values. This was necessary for my Entities without Tracking:
// load entity without tracking
var entityWithoutTracking = Context.Person.AsNoTracking().FirstOrDefault(x => x.ID == _entity.ID);
var entityInit = CopyEntity(entityWithoutTracking);
// do business logic and change entity
entityWithoutTracking.surname = newValue;
// for saving, find entity in context
var entity = Context.Person.FirstOrDefault(x => x.ID == _entity.ID);
var entry = Context.Entry(entity);
entry.CurrentValues.SetValues(entityWithoutTracking);
entry.State = EntityState.Modified;
// get List of all changed properties (in my case these are all existing properties, including those which shouldn't have changed)
var changedPropertiesList = entry.CurrentValues.PropertyNames.Where(x => entry.Property(x).IsModified).ToList();
foreach (var checkProperty in changedPropertiesList)
{
try
{
var p1 = entityWithoutTracking.GetType().GetProperty(checkProperty).GetValue(entityWithoutTracking);
var p2 = entityInit.GetType().GetProperty(checkProperty).GetValue(entityInit);
if ((p1 == null && p2 == null) || p1.Equals(p2))
{
entry.Property(checkProperty).CurrentValue = entry.Property(checkProperty).OriginalValue; // restore DB-Value
entry.Property(checkProperty).IsModified = false; // throws Exception for Primary Keys
}
} catch(Exception) { }
}
Context.SaveChanges(); // only surname will be updated
This is way I did it, assuming the new object has more columns to update that the one we want to keep.
if (theClass.ClassId == 0)
{
theClass.CreatedOn = DateTime.Now;
context.theClasses.Add(theClass);
}
else {
var currentClass = context.theClasses.Where(c => c.ClassId == theClass.ClassId)
.Select(c => new TheClasses {
CreatedOn = c.CreatedOn
// Add here others fields you want to keep as the original record
}).FirstOrDefault();
theClass.CreatedOn = currentClass.CreatedOn;
// The new class will replace the current, all fields
context.theClasses.Add(theClass);
context.Entry(theClass).State = EntityState.Modified;
}
context.SaveChanges();
In EF you can do like this
var result = db.Person.Where(x => x.ID == model.ID).FirstOrDefault();
if(result != null){
result.Name = newName;
result.DOB = newDOB;
db.Person.Update(result);
}
Or you can use
using (var db= new MyDbContext())
{
var result= db.Person.Where(x => x.ID == model.ID).FirstOrDefault();
result.Name= newName;
result.DOB = newDOB;
db.Update(result);
db.SaveChanges();
}
For more detail please EntityFramework Core - Update Only One Field
No Worry guys
Just write raw sql query
db.Database.ExecuteSqlCommand("Update Person set Name='"+_entity.Name+"' where Id = " + _entity.ID + "");

How to return partial results and the total count for a query with Entity Framework?

I have this query with Entity Framework:
_context.Onlines
.Where(x => x.Date >= startDate.Date && x.Date <= endDate.Date && x.User.Id == userId)
.OrderByDescending(x => x.Date)
.Skip((int)size * (page - 1))
.Take((int)size)
.ToList();
How you can see, I'm doing a pagination search with "Skip" and "Take", and I need to enjoy this query to count the total results for this query (not only the partial count with pagination), and return the results, everything in the same request to the database.
I need this for calculating the pagination in the View.
You can do it in such way:
var query = _context.Onlines
.Where(x => x.Date >= startDate.Date && x.Date <= endDate.Date && x.User.Id == userId);
// getting just count
int totalCount = query.Count();
// and then getting items itself
var items = query
.OrderByDescending(x => x.Date)
.Skip((int)size * (page - 1))
.Take((int)size)
.ToList();
It will produce two SQL queries based on original conditions. One for count, and second one for items.
There's a way you can do this in one transaction using Entity Framework Extended. It's a nuget package you can find. I'll walk you through what we decided on doing for our server side pagination.
We need the list that is returned and the count of total records. A KeyValuePair<int, List<WhateverReturnModel>> should work nicely.
Lets take a look at what our requests should now take.
Create a pagination request model that has a default PageNumber of x and a PageSize of z.
public class PagedRequest
{
private int? _pageNumber;
private int? _pageSize;
private int? _pageSkip;
public int PageNumber
{
get { return this._pageNumber ?? 1; }
set { this._pageNumber = value; }
}
public int PageSize
{
get { return this._pageSize ?? 15; }
set { this._pageSize = value; }
}
}
Setup your return method to handle the KeyValuePair result
protected KeyValuePair<int, List<T>> PagedResult<T>(int count, List<T> list)
{
return new KeyValuePair<int, List<T>>(count, list);
}
Add these to your endpoints that require paging
public KeyValuePair<int, List<WhateverModel>> DoSomething([FromUri] PagedRequest paged)
{
var records = yourContext.YourTable.Where(t => true);
var count = records.FutureCount() // this will not execute right away.. only when it is finally called
var data = yourContext.YourTable
.Where(t => t.Something)
.OrderBy(i => i.Anything)
.Skip(this.PageSkip(paged.PageNumber, paged.PageSize))
.Take(paged.PageSize)
.Future() // again this will not execute right away
return this.PagedResult(count, data.ToList()); // now both queries will execute in one call
}
An API method consuming the paginated method.
public HttpResponseMessage DoAnotherThing()
{
var test = new WhateverClass.DoSomething();
return this.Paged(test);
}
You can then write the method Paged() where it will return the KeyValuePair Value as the response Content and you can add a header for the total count. Something like this..
protected HttpResponseMessage OkPaged<T>(KeyValuePair<int, List<T>> content)
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ObjectContent<Object>(content.Value, this.GetConfiguration().Formatters.JsonFormatter)
};
response.Headers.Add("x-paging-total", content.Key.ToString());
return response;
}
Doing both in the single query will not yield any performance benefit. However, the pagination data can be captured in an elegant way using a nuget package EntityFrameworkPaginate. The way it works is you set up your dynamic filtering and sorting and you will get a Page object as result which will have the result along with the metadata. (CurrentPage, PageCount, PageSize, RecordCount and Results).
First you need to setup your filters. In your case you have one condition. In scenario where you have multiple where clause based on different conditions, you can add those filters to the Filters object.
var filters = new Filters<Onlines>();
filters.Add(true, x => x.Date >= startDate.Date
&& x.Date <= endDate.Date && x.User.Id == userId);
Next, you need to set up your order by. Again in your case there is just one, but Sorts class can handle dynamic sorting as well.
var sorts = new Sorts<Onlines>();
sorts.Add(true, x => x.Date, true);
Now to finally get your paginated data, you need to call the extension method paginate on your dbset.
Page<Onlines> paginatedData = context.Employees.Paginate(page, size, sorts, filters);
Voila, you will get the paginated data with all the required metadata. This provides a clean approach and is very helpful when you have dynamic filtering and sorting. You can check the detailed article here.

How to handle children updates in EF

I have an action
[HttpPost]
public string Edit(Member member)
and Member has a collection of children entities ICollection<AgeBracket> AgeBrackets.
Currently I do retrieve all AgeBrackets associated with the member, mark everyone as deleted, then loop through new collection and create a new entry for each. Then I update my parent entity. It works, but there should be a better way to do it:
for example, if I would wrote SQL, I could delete all existing children with just one line
DELETE FROM AgeBrackets WHERE MemberId = #MemberId
In my situation it makes a select to retrieve existing items, then generate delete for each of them, then generate insert for each new child and then it generates update for parent.
Here is how my code looks now:
IList<AgeBracket> ageBrackets = db.AgeBrackets.Where<AgeBracket>(x => x.MemberId == member.MemberId).ToList();
foreach (AgeBracket ab in ageBrackets)
db.Entry(ab).State = EntityState.Deleted;
if (member.AgeBrackets != null)
foreach (AgeBracket ab in member.AgeBrackets)
{
ab.MemberId = member.MemberId;
db.AgeBrackets.Add(ab);
}
db.Entry(member).State = EntityState.Modified;
Initially I was trying to query existing children and compare each of them to new set, but it seems to be over-complicated.
What is the best way to update member and all it's children?
There's another way to do
var originalAgeBrackets = db.AgeBrackets.Where(x => x.MemberId == member.MemberId).ToArray();
var currentAgeBrackets = member.AgeBrackets;
foreach (var original in originalAgeBrackets) {
// check if the original age brackets were modified ou should be removed
var current = currentAgeBrackets.FirstOrDefault(c => c.AgeBracketId == original.AgeBracketId);
if(current != null) {
var entry = db.Entry(original);
entry.OriginalValues.SetValues(original);
entry.CurrentValues.SetValues(current);
} else {
db.Entry(original).State = EntityState.Deleted;
}
}
// add all age brackets not listed in originalAgeBrackets
foreach (var current in currentAgeBrackets.Where(c => !originalAgeBrackets.Select(o => o.AgeBracketId).Contains(c.AgeBracketId))) {
db.AgeBrackets.Add(current);
}
db.SaveChanges();
Unfortunately what you want to do haven't native support to EF Code First. What will help you would be EntityFramework.Extended. This will allow you to do something like:
db.AgeBrackets.Delete(a => a.MemberId == member.MemberId);
You should take care of change-tracks by yourself.
Hope it helps you.

Resources