Call a method in Linq to EF - asp.net-mvc

In order to create a ViewModel, I tried to call a method GetName() to find the FirstName and LastName for UserID and then add it to the model. But the error tells "Linq to Entities does not recognize the method".
How do I accomplish this in another way?
My code:
public IQueryable<SheetList> GetSheetData()
{
var query = from a in GetSheets()
select new SheetList
{
SheetId = a.ListAllSafetySheets.Id,
SheetTitle = a.ListAllSafetySheets.SafetySheetTitle,
ProductionManagerId = a.ListAllSafetySheets.ProductionManager,
ProductionManagerName = this.GetName(a.ListAllSafetySheets.ProductionManager),
ConstructionManagerId = a.ListAllSafetySheets.ConstructionManager,
Created = a.ListAllSafetySheets.Created,
CreatedBy = a.ListAllSafetySheets.CreatedBy,
UserProfile_UserId = a.ListAllUserProfiles.UserId,
Project_Id = a.ListAllProjects.Id,
ProjectLeaderId = a.ListAllProjects.ProjectLeader,
ConstructionLocation_Id = a.ListAllConstructionLocations.Id,
};
return query;
}
public IQueryable<DataCollection> GetSheets()
{
var query = from vSafety in _db.Sheets
join vUserProfile in _db.UserProfiles
on vSafety.Id
equals vUserProfile.UserId
join vProject in _db.Projects
on vSafety.Id
equals vProject.Id
join vConstructionLocation in _db.ConstructionLocations
on vSafety.Id
equals vConstructionLocation.Id
orderby vSafety.Created descending
select new SafetyAndProjectAndUserAndLocationCollection
{
ListAllSafetySheets = vSafety,
ListAllUserProfiles = vUserProfile,
ListAllProjects = vProject,
ListAllConstructionLocations = vConstructionLocation
};
return query;
}
public string GetName(int? id)
{
string returnValue;
if (id == null)
{
var userModel = _db.UserProfiles.Single(x => x.UserId == id);
string FirstName = userModel.FirstName;
string LastName = userModel.LastName;
returnValue = FirstName + ", " + LastName;
}
else
{
returnValue = "";
}
return returnValue;
}

You'll need to call the method after you build the model. You can try something like this:
public IQueryable<SheetList> GetSheetData()
{
var query = from a in GetSheets()
select new SheetList
{
SheetId = a.ListAllSafetySheets.Id,
SheetTitle = a.ListAllSafetySheets.SafetySheetTitle,
ProductionManagerId = a.ListAllSafetySheets.ProductionManager,
ProductionManagerName = a.ListAllSafetySheets.ProductionManager,
ConstructionManagerId = a.ListAllSafetySheets.ConstructionManager,
Created = a.ListAllSafetySheets.Created,
CreatedBy = a.ListAllSafetySheets.CreatedBy,
UserProfile_UserId = a.ListAllUserProfiles.UserId,
Project_Id = a.ListAllProjects.Id,
ProjectLeaderId = a.ListAllProjects.ProjectLeader,
ConstructionLocation_Id = a.ListAllConstructionLocations.Id,
};
var queryWithNames = query.ToList().ForEach(s => s.ProductionManagerName = this.GetName(s.ProductionManagerName));
return queryWithNames;
}
Since you're having trouble using .ForEach(), you can do this with a regular foreach loop:
foreach(var s in query)
{
s.ProductionManagerName = this.GetName(s.ProductionManagerName);
}
The downside to this is the call to .ToList will enumerate the queryable, executing the query against the database, so if you need to do further filters later outside this method, you may be downloading additional data that you don't need, causing additional overhead.

Related

am working on updating a single attribute in the User Model which is the balance attribute,

how I can update a single value for an already existing row in the db by only having a parameters that I want to add it to this attribute
here is my code for a trivial way but didnt work
public bool BuyBook(int BookId, int UserId, int BookPrice){
using (var ctx = new OnlineBooksEntities())
{
User updatedCustomer = (from c in ctx.Users
where c.UserId == UserId
select c).FirstOrDefault();
updatedCustomer.Balance = BookPrice;
ctx.SaveChanges();
}
this.DeleteBook(BookId);
return true;
}
Add an sql query to the method solves the update aim
public bool BuyBook(int BookId, int UserId, int BookPrice)
{
try
{
using (var ctx = new OnlineBooksEntities())
{
User user = ctx.Users.Where(x => x.UserId == UserId).FirstOrDefault();
BookPrice = (int)user.Balance + BookPrice;
int noOfRowUpdated =
ctx.Database.ExecuteSqlCommand("Update Users set Balance = "+BookPrice+ " where UserId ="+UserId);
}
Updating basically means changing an existing row's value. Since you mentioned EF, you can do this by retrieving the object, changing its value, and saving it back. Thus you can do something like this:
using (var db = new MyContextDB())
{
var result = db.Books.SingleOrDefault(b => b.BookPrice == bookPrice);
if (result != null)
{
result.SomeValue = "Your new value here";
db.SaveChanges();
}
}

How to save data in multiple tables using Entity Framework?

How to save mixed data in multiple tables if is checked checkbox:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "rID,AgentID,karta_br,Datum,patnikID,stanicaOD,stanicaDO,cena,povratna")] tbl_rezervacii tbl_rezervacii)
{
if (ModelState.IsValid)
{
if (tbl_rezervacii.povratna != true)
{
db.tbl_rezervacii.Add(tbl_rezervacii);
db.SaveChanges();
}
else
{
tbl_rezervacii rezervacii = new tbl_rezervacii()
{
???????????????????????
};
db.tbl_rezervacii.Add(rezervacii);
db.SaveChanges();
tbl_povratni povratni = new tbl_povratni()
{
???????????????????????
};
db.tbl_povratni.Add(povratni);
db.SaveChanges();
}
This is code in the controller, and I need to mix data from two forms, and save to two tables, I need something like this, and now my problem is just in else section of implementation.
I make application for Bus Ticket system, and i need this if is checked return way checkbox to add: rID (related with first table tbl_rezervacii), date of returning and relation of returning, include same agent id, price, etc. data which is saved in first tbl_rezervacii table.
MODIFIED CONTROLLER CODE:
public ActionResult Create([Bind(Include = "rID,AgentID,karta_br,Datum,patnikID,stanicaOD,stanicaDO,cena,povratna")] tbl_rezervacii tbl_rezervacii )
{
if (ModelState.IsValid)
{
if (tbl_rezervacii.povratna != true)
{
db.tbl_rezervacii.Add(tbl_rezervacii);
db.SaveChanges();
}
else
{
tbl_rezervacii rezervacii = new tbl_rezervacii()
{
AgentID = tbl_rezervacii.AgentID,
karta_br = tbl_rezervacii.karta_br,
Datum = tbl_rezervacii.Datum,
patnikID = tbl_rezervacii.patnikID,
stanicaOD = tbl_rezervacii.stanicaOD,
stanicaDO = tbl_rezervacii.stanicaDO,
cena = tbl_rezervacii.cena,
povratna = tbl_rezervacii.povratna
};
db.tbl_rezervacii.Add(rezervacii);
//db.SaveChanges();
var rows = db.SaveChanges();
tbl_povratni povratna = new tbl_povratni()
{
rezID = rezervacii.rID,
AgentID = rezervacii.AgentID,
karta_br = rezervacii.karta_br,
DatumP = **tbl_povratni.DatumP**,
patnikID = rezervacii.patnikID,
stanicaPOD = **tbl_povratni.stanicaPOD**,
stanicaPDO = **tbl_povratni.stanicaPDO**,
};
db.tbl_povratni.Add(povratna);
db.SaveChanges();
}
ViewBag.AgentID = new SelectList(db.tbl_agenti, "aID", "agent_ime", tbl_rezervacii.AgentID);
ViewBag.patnikID = new SelectList(db.tbl_patnici, "pID", "ime", tbl_rezervacii.patnikID);
ViewBag.stanicaOD = new SelectList(db.tbl_stanici, "sID", "stanica", tbl_rezervacii.stanicaOD);
ViewBag.stanicaDO = new SelectList(db.tbl_stanici, "sID", "stanica", tbl_rezervacii.stanicaDO);
ViewBag.stanicaPOD = new SelectList(db.tbl_stanici, "sID", "stanica", tbl_rezervacii.tbl_povratni.stanicaPOD);
ViewBag.stanicaPDO = new SelectList(db.tbl_stanici, "sID", "stanica", tbl_rezervacii.tbl_povratni.stanicaPDO);
return View(tbl_rezervacii);
}
return RedirectToAction("Index");
}
How to take data from secondary form and save together in second table?
So, if checkbox is checked, you want to save data into two tables and use primary key of first table (rID) in second table? If rID is auto increment, It will be updated by EF with the value assigned by the database.
tbl_rezervacii rezervacii = new tbl_rezervacii()
{
AgentID = tbl_rezervacii.AgendID,
karta_br = tbl_rezervacii.karta_br
// and so on...
};
db.tbl_rezervacii.Add(rezervacii);
var rows = db.SaveChanges(); // optional, rows will be > 0 if saved successfully.
tbl_povratni povratni = new tbl_povratni()
{
// if rID is auto increment
rID = rezervacii.rID,
// and so on...
};
db.tbl_povratni.Add(povratni);
db.SaveChanges();

Xamarin Android, get contact mobile number by using CursorLoader with selection and selection args

I'm trying to get contact details of a contact that the user picks from the contacts list in Android using Intent as the following code:
Intent Intent = new Intent(Intent.ActionPick, ContactsContract.Contacts.ContentUri);
Intent.SetType(ContactsContract.Contacts.ContentType);
StartActivityForResult(Intent, 3);
Now on the Intent results I run the following code to get specific contact information:
public override void OnActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == 3 && resultCode == -1 && data != null) //result code -1 means OK 0 Means cancelled Result.Ok
{
var ContactData = data.Data;
string ID = "";
string name = "";
string address = "";
byte[] picture = new byte[0];
List<string> numbers = new List<string>();
List<string> emails = new List<string>();
string mobile = "";
string email = "";
string selectionString = "id = ?";
string[] columnsNames = new string[] {
ContactsContract.Contacts.InterfaceConsts.Id,
ContactsContract.Contacts.InterfaceConsts.DisplayName,
ContactsContract.Contacts.InterfaceConsts.PhotoUri
};
var loader = new CursorLoader(Statics.mainActivity, ContactData, null, null, null, null);
var cursor = (ICursor)loader.LoadInBackground();
if (cursor.MoveToFirst())
{
ID = cursor.GetString(cursor.GetColumnIndex(columnsNames[0]));
name = cursor.GetString(cursor.GetColumnIndex(columnsNames[1]));
picture = cursor.GetBlob(cursor.GetColumnIndex(columnsNames[2]));
}
//Store Contact ID
string[] selectionStringArgs = new string[] { ID };
//Phone Numbers
string[] columnsNames2 = new string[] {
ContactsContract.CommonDataKinds.Phone.Number
};
var loader2 = new CursorLoader(Statics.mainActivity, ContactsContract.CommonDataKinds.Phone.ContentUri, columnsNames2, selectionString, selectionStringArgs, null);
var cursor2 = (ICursor)loader2.LoadInBackground();
while (cursor2.MoveToNext())
{
numbers.Add(cursor2.GetString(cursor2.GetColumnIndex(columnsNames2[0])));
}
//Email Address
string[] columnsNames3 = new string[] {
ContactsContract.CommonDataKinds.Email.Address
};
var loader3 = new CursorLoader(Statics.mainActivity, ContactsContract.CommonDataKinds.Email.ContentUri, columnsNames3, selectionString, selectionStringArgs, null);
var cursor3 = (ICursor)loader3.LoadInBackground();
while (cursor3.MoveToNext())
{
emails.Add(cursor3.GetString(cursor3.GetColumnIndex(columnsNames3[0])));
}
int TempRecepitntID = 0;
EmployeesViewModel tempRecipent = new EmployeesViewModel();
TempRecepitntID = Statics.mainActivity.currentViewModel.SelectedChat.ReceiverEmployee;
foreach (EmployeesViewModel evm in Statics.mainActivity.currentViewModel.Employees)
{
if (evm.ID == TempRecepitntID)
tempRecipent = evm;
}
new Android.Support.V7.App.AlertDialog.Builder(Statics.mainActivity)
.SetPositiveButton("Yes", (sender1, args) =>
{
Statics.mainActivity.currentViewModel.AddMessage(picture, tempRecipent, Statics.mainActivity.currentViewModel.SelectedChat.ID, "contact", 0, "", name, numbers[0], mobile, email, address);
})
.SetNegativeButton("No", (sender1, args) =>
{
// cancel
})
.SetMessage("Are you shure you want to send?")
.SetTitle("System Message")
.Show();
}
}
The problem is I want to retrieve only the information of the contact that the user selected but what I get is all other contacts data is retrieved so I tried to use the selection and selectionargs parameters of CursorLoader by setting string selectionString = "id = ?"; and selectionArgs to string[] selectionStringArgs = new string[] { ID }; the ID value is retrieved from the following code :
if (cursor.MoveToFirst())
{
ID = cursor.GetString(cursor.GetColumnIndex(columnsNames[0]));
name = cursor.GetString(cursor.GetColumnIndex(columnsNames[1]));
picture = cursor.GetBlob(cursor.GetColumnIndex(columnsNames[2]));
}
//Store Contact ID
string[] selectionStringArgs = new string[] { ID };
//Phone Numbers
string[] columnsNames2 = new string[] {
ContactsContract.CommonDataKinds.Phone.Number
};
But now it returns 0 results, I couldn't find anything on the internet that applies to Xamarin android, Please help.
Thanks,
Finally I found the solution, I used the following string in the selection parameter of the cursorloader method:
string selectionString = ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId + "=" + ID;
and now only the selected contact numbers are retrieved.
I hope this will help someone else.
In additional information of #TMSL, I add the code afer this bloque
if (cursor.MoveToFirst())
{
ID = cursor.GetString(cursor.GetColumnIndex(columnsNames[0]));
name = cursor.GetString(cursor.GetColumnIndex(columnsNames[1]));
picture = cursor.GetBlob(cursor.GetColumnIndex(columnsNames[2]));
}
Here
selectionString = ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId + "=" + ID;
Then I changed the parameters used in the definition of variable Loader2, converting selectionStringArgs in null.
var loader2 = new CursorLoader(this.Activity, ContactsContract.CommonDataKinds.Phone.ContentUri, columnsNames2, selectionString, null,null);
var cursor2 = (ICursor)loader2.LoadInBackground();
I found this documentation from xamarin guides
Uri – The fully qualified name of the ContentProvider.
Projection – Specification of which columns to select for the cursor.
Selection – Similar to a SQL WHERE clause.
SelectionArgs – Parameters to be substituted in the Selection.
SortOrder – Columns to sort by.
So, the variable selectionStringArgs used in the code from #TMSAL cannot use a value like "contact_id = 2700", because the parameter of CursorLoader SelectionArgs is not a filter but not "Parameters to be substituted in the Selection"
I hope this will help someone else too.

Will breaking out the context calls cause multiple trips to the database?

I'm refactoring some previously written MVC and Entity Framework code. The way the initial code was written they called a DAL.GetGroupDetail(int groupId) method. In that method it created a ViewModel and populated several properties. Some of those properties are Lists for things like CostCenters, Cities, Groups. I want to break those calls out into their own methods so that they can be re-used in other controllers.
My question is that doing that I'm creating new Contexts using the Using statement. My understanding is that would create multiple connections to the database and thus would slow down the site if multiple users were using it at the same time?
Example, currently this is the basic code:
public ClockGroupViewModel GetClockGroupDetail(int groupId)
{
GroupViewModel cgdv = new GroupViewModel();
using (var ctx = new VTContext())
{
bio_group group = ctx.bio_group.Where(x => x.group_id == groupId).FirstOrDefault();
cgdv.GroupId = group.group_id;
cgdv.GroupName = group.group_name;
cgdv.Cities = ctx.bio_city.ToList();
var clocks = from c in ctx.bio_clock.Where(x => x.group_id == groupId)
select new ClockViewModel
{
ClockID = c.rdr_id.ToString(),
ClockDescription = c.clock_desc,
};
cgdv.ClockList = clocks.ToList();
cgdv.CostCtrList = (from g in ctx.bio_clock_group
from cgc in ctx.bio_clock_group_costctr
where cgc.group_id == g.group_id && g.group_id == groupId
select cgc.cost_ctr).ToList();
}
This how I'm thinking of changing it:
public ClockGroupViewModel GetClockGroupDetail(int groupId)
{
GroupViewModel cgdv = new GroupViewModel();
using (var ctx = new VTContext())
{
bio_group group = ctx.bio_group.Where(x => x.group_id == groupId).FirstOrDefault();
cgdv.GroupId = group.group_id;
cgdv.GroupName = group.group_name;
cgdv.Cities = GetCityList();
cgdv.ClockList = GetClockGroupClockList(group.group_id);
cgdv.CostCtrList = GetGroupCostCenter(group.group_id);
}
}
public List<bio_clock_city> GetCityList()
{
using (var ctx = new VTContext())
{
return ctx.bio_city.ToList();
}
}
public List<ClockViewModel> GetClockGroupClockList(int groupId)
{
using (var ctx = new VTContext())
{
var data = (from c in ctx.bio_clock.Where(x => x.group_id == groupId)
select new ClockViewModel
{
ClockID = c.rdr_id.ToString(),
ClockDescription = c.clock_desc,
}).ToList();
return data;
}
}
public List<string> GetGroupCostCenter(int groupId)
{
using (var ctx = new VTContext())
{
var data = (from g in ctx.bio_clock_group
from cgc in ctx.bio_clock_group_costctr
where cgc.group_id == g.group_id && g.group_id == groupId
select cgc.cost_ctr).ToList();
return data;
}
}

System.data.entity.validation.DbEntityValdationException Error Come when save the data

This my Controller
public JsonResult SaveBillingSystemParameters(BillingSystemParameters model)
{
var id = -1;
//Initialize the newId variable
var userId = Helpers.GetLoggedInUserId();
var currentDate = Helpers.GetInvariantCultureDateTime();
var defaultCorporateId = Helpers.GetSysAdminCorporateID();
//Check if Model is not null
if (model != null)
{
using (var bal = new BillingSystemParametersBal())
{
model.CorporateId = defaultCorporateId;
if (model.Id > 0)
{
model.ModifiedBy = userId;
model.ModifiedDate = currentDate;
}
else
{
model.CreatedBy = userId;
model.CreatedDate = currentDate;
model.CorporateId = Helpers.GetSysAdminCorporateID();
}
//Call the AddBillingSystemParameters Method to Add / Update current BillingSystemParameters
id = bal.SaveBillingSystemParameters(model);
}
}
return Json(id);
}
//Bal class
public int SaveBillingSystemParameters(BillingSystemParameters model)
{
using (var rep = UnitOfWork.BillingSystemParametersRepository)
{
if (model.Id > 0)
{
var current = rep.GetSingle(model.Id);
model.CreatedBy = current.CreatedBy;
model.CreatedDate = current.CreatedDate;
rep.UpdateEntity(model, model.Id);
}
else
rep.Create(model);
return model.Id;
}
}
I am getting following error
do what exception message says, inspect EntityValidationErrror
this exception usually means you're trying to break some constraint like varchar filed width
if you browse through this param you'll get more details on type of constrain SaveChanges() tried to brake

Resources