save new or update exist record with linq - linq

this is the way i used to save record with linq: (my Q is below)
public void SaveEmployee(Employee employee)
{
using (BizNetDB db = new BizNetDB())
{
BizNet.SqlRep.Data.Employee oldEmployee = (from e in db.Employees
where e.EmployeeID == employee.EmployeeID
select e).SingleOrDefault();
if (oldEmployee == null)
{
oldEmployee = new BizNet.SqlRep.Data.Employee();
oldEmployee.BirthDate = employee.BirthDate;
oldEmployee.WorkRole = employee.WorkRole;
oldEmployee.CurrentFlag = employee.CurrentFlag;
oldEmployee.HireDate = employee.HireDate;
...
db.Employees.InsertOnSubmit(oldEmployee);
}
else
{
if (oldEmployee.BirthDate.Date != employee.BirthDate.Date)
oldEmployee.BirthDate = employee.BirthDate;
if (oldEmployee.CurrentFlag != employee.CurrentFlag)
oldEmployee.CurrentFlag = employee.CurrentFlag;
if (oldEmployee.HireDate.Date != employee.HireDate.Date)
oldEmployee.HireDate = employee.HireDate;
}
oldEmployee.ModifiedDate = DateTime.Now;
db.SubmitChanges();
employee.EmployeeID = oldEmployee.EmployeeID;
}
}
my questions are:
a. are the if statements nesccery? why not to make the assigning without the
check?
mybe the if block take more cpu..
b. why to spearate the new record block and the update block?
when the record is new it will do
db.Employees.InsertOnSubmit(oldEmployee);
and then proceed with the update routine...

The way you're doing it the only reason you need the if statement is to new it up and insert it, so I would use the if statement just for that.
I would do this instead:
public void SaveEmployee(Employee employee)
{
using (BizNetDB db = new BizNetDB())
{
BizNet.SqlRep.Data.Employee oldEmployee =
(from e in db.Employees
where e.EmployeeID == employee.EmployeeID
select e).SingleOrDefault();
if (oldEmployee == null)
{
oldEmployee = new BizNet.SqlRep.Data.Employee();
db.Employees.InsertOnSubmit(oldEmployee);
}
if (oldEmployee.BirthDate.Date != employee.BirthDate.Date)
oldEmployee.BirthDate = employee.BirthDate;
if (oldEmployee.CurrentFlag != employee.CurrentFlag)
oldEmployee.CurrentFlag = employee.CurrentFlag;
if (oldEmployee.HireDate.Date != employee.HireDate.Date)
oldEmployee.HireDate = employee.HireDate;
oldEmployee.ModifiedDate = DateTime.Now;
db.SubmitChanges();
employee.EmployeeID = oldEmployee.EmployeeID;
}
}
I also think there's a way to map one object's properties to the other, but it escapes me at the moment. It may not work for what you're trying to do anyway since it seems that you're doing some other things later anyway with the ModifiedDate and EmployeeID.

Related

Comparing objects before and after update retrieved by LINQ query

I am using LINQtoSQL and I need to compare object before and after update.
In the example below Student 'before' and Student 'curStudent' are the same, because they was retrieved by the same query.
using(DataContext db = new DataContext())
{
Student before = db.Student.Where(q=>q.id == 1).SingleOrDefault();
Student curStudent = db.Student.Where(q=>q.id == 1).SingleOrDefault();
curStudent.Name = "NewName";
db.SubmitChanges();
}
if(before.Name != curStudent.Name) // this condition will never be true
{
//do something
}
The context will only keep one object per key value, so one way would be to use two separate contexts:
Student before;
using(DataContext db1 = new DataContext())
{
before = db.Student.Where(q=>q.id == 1).SingleOrDefault();
}
Student curStudent;
using(DataContext db2 = new DataContext())
{
curStudent = db.Student.Where(q=>q.id == 1).SingleOrDefault();
curStudent.Name = "NewName";
db.SubmitChanges();
}
if(before.Name != curStudent.Name)
{
//do something
}
Or if you're just interested in the name change, keep the previous value:
string before;
using(DataContext db = new DataContext())
{
Student curStudent = db.Student.Where(q=>q.id == 1).SingleOrDefault();
before = curStudent.Name; // cache the name
curStudent.Name = "NewName";
db.SubmitChanges();
}
if(before != curStudent.Name)
{
//do something
}

LINQ dont want display in ASP.NET MVC

I want to display all records from table of current autorized user in my ASP.NET-MVC 3 + SQL Server 2008 app. But I have some problems:
this code with LINQ-request working good:
public ActionResult Index(todo obj)
{
string u = User.Identity.Name;
var th = (from tt in _db.todo select tt);
return View(th);
}
but this code not work:
public ActionResult Index(todo obj)
{
string u = User.Identity.Name;
var th = (from tt in _db.todo where obj.login == u select tt);
return View(th);
}
and this code is working good
if (u == obj.login) { ViewBag.res = "ok"; } else { ViewBag.res = "fail"; }
What I do wrong, please help me.
You probably want to run your where criteria against the table you're querying, instead of against the argument from the method, i.e.:
var th = (from tt in _db.todo where tt.login == u select tt);
instead of obj.login == u, try
obj.Contains(u)

Problem returning an IEnumerable<T>/IList<T>

I am having trouble to return an IEnumerable and IList, I cant do it!
I am using EF 4 with POCOs
Here's the whole method:
//public IList<Genre> GetGenresByGame(int gameId)
public IEnumerable<Genre> GetGenresByGame(int gameId)
{
using(var ctx = new XContext())
{
var results =
from t0 in ctx.GameGenres
join t1 in ctx.GenreCultureDetails on t0.GenreId equals t1.GenreId
where t0.GameId == gameId && t1.CultureId == _cultureId
select new Genre
{
GenreId = t0.GenreId,
GenreName = t1.GenreName
};
return results.ToList();
}
}
I have tried different ways that I have found on the net.. but can't make it work!
Question 2:
I saw a screencast with Julie something, saying that "You should always return an ICollection" when using EF4.
Any thoughts about that ?
BR
EDIT:
When I load the page in Debug-mode i get these errors: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection. OR The entity or complex type 'XModel.Genre' cannot be constructed in a LINQ to Entities query.
Genre must not be a L2EF type. Try this:
public IEnumerable<Genre> GetGenresByGame(int gameId)
{
using(var ctx = new XContext())
{
var resultList =
from t0 in ctx.GameGenres
join t1 in ctx.GenreCultureDetails on t0.GenreId equals t1.GenreId
where t0.GameId == gameId && t1.CultureId == _cultureId
select new { t0.GenreId, t1.GenreName };
var genres = resultList.AsEnumerable().Select(o => new Genre
{
GenreId = o.GenreId,
GenreName = o.GenreName
});
return genres.ToList();
}
}
First an foremost if Genre is in the database you should select it? If you have FKs from Genre->GenreCultureDetails let me know and I can update the below, but from the looks of it you could do it like this:
using(var ctx = new XContext())
{
var results =
from g in ctx.Genre
join gcd in ctx.GenreCultureDetails on g.GenreId equals gcd.GenreId
where g.GameId == gameId && gcd.CultureId == _cultureId
select g;
return result.ToList();
}
Alternatively continue down your path select them into an annoynmous type, and then copy them. You can use select instead of convertall if you please.
IList<Genre> returnMe = Null;
using(var ctx = new XContext())
{
var results =
from t0 in ctx.GameGenres
join t1 in ctx.GenreCultureDetails on t0.GenreId equals t1.GenreId
where t0.GameId == gameId && t1.CultureId == _cultureId
select new
{
GenreId = t0.GenreId,
GenreName = t1.GenreName
};
returnMe = results.ToList().ConvertAll(x=>new Genre(){
GenreId = x.GenreId,
GenreName = x.GenreName
}
);
}
return returnMe;

LINQ to ADO.NET Entity Data Modelassign value to object

Can I assign values to user object without looping in query result? I don't need looping there will be only one or no return from the query.
protected user GetUser(user u, string name, string password)
{
using (DBEntities db = new DBEntities())
{
var selectedUser = from p in db.users
where p.name == name && p.pass == password
select p;
if (selectedUser.Count() == 1)
{
foreach (user us in selectedUser)
{
u.id = us.id;
u.name = us.name;
u.pass = us.pass;
}
}
return u;
}
}
I guess you are looking for:
using (var db = new DBEntities())
{
return db.users.SingleOrDefault(u => u.name == name && u.pass == password);
}

Update using LINQ to SQL

How can I update a record against specific id in LINQ to SQL?
LINQ is a query tool (Q = Query) - so there is no magic LINQ way to update just the single row, except through the (object-oriented) data-context (in the case of LINQ-to-SQL). To update data, you need to fetch it out, update the record, and submit the changes:
using(var ctx = new FooContext()) {
var obj = ctx.Bars.Single(x=>x.Id == id);
obj.SomeProp = 123;
ctx.SubmitChanges();
}
Or write an SP that does the same in TSQL, and expose the SP through the data-context:
using(var ctx = new FooContext()) {
ctx.UpdateBar(id, 123);
}
In the absence of more detailed info:
using(var dbContext = new dbDataContext())
{
var data = dbContext.SomeTable.SingleOrDefault(row => row.id == requiredId);
if(data != null)
{
data.SomeField = newValue;
}
dbContext.SubmitChanges();
}
AdventureWorksDataContext db = new AdventureWorksDataContext();
db.Log = Console.Out;
// Get hte first customer record
Customer c = from cust in db.Customers select cust where id = 5;
Console.WriteLine(c.CustomerType);
c.CustomerType = 'I';
db.SubmitChanges(); // Save the changes away
DataClassesDataContext dc = new DataClassesDataContext();
FamilyDetail fd = dc.FamilyDetails.Single(p => p.UserId == 1);
fd.FatherName=txtFatherName.Text;
fd.FatherMobile=txtMobile.Text;
fd.FatherOccupation=txtFatherOccu.Text;
fd.MotherName=txtMotherName.Text;
fd.MotherOccupation=txtMotherOccu.Text;
fd.Phone=txtPhoneNo.Text;
fd.Address=txtAddress.Text;
fd.GuardianName=txtGardianName.Text;
dc.SubmitChanges();
I found a workaround a week ago. You can use direct commands with "ExecuteCommand":
MDataContext dc = new MDataContext();
var flag = (from f in dc.Flags
where f.Code == Code
select f).First();
_refresh = Convert.ToBoolean(flagRefresh.Value);
if (_refresh)
{
dc.ExecuteCommand("update Flags set value = 0 where code = {0}", Code);
}
In the ExecuteCommand statement, you can send the query directly, with the value for the specific record you want to update.
value = 0 --> 0 is the new value for the record;
code = {0} --> is the field where you will send the filter value;
Code --> is the new value for the field;
I hope this reference helps.

Resources