I have this weird problem that has burned way more hours than it should.
My main question is this:
What may cause EF 4.1 Code First to set a foreign key to NULL when an entity is added?
The problem is this: I have a list of users on file, and these users must be inserted to my database if they're not already there.
I have something like this:
foreach (var u in usersFromFile) {
var userProfile = context.Users
.FirstOrDefault(user=>
user.EmployeeId == u.EmployeeId && user.CompanyId == 1);
if (userProfile == null) {
User newUser = new User();
newUser.EmployeeId = u.EmployeeId;
newUser.CompanyId = 1;
context.Users.Add(newUser); //This will sometimes set CompanyId = NULL
}
}
context.SaveChanges();
Some users won't be added to the Users table correctly.
They get CompanyId == NULL, and as such they do not belong to the company.
I also tried injecting SQL directly like so:
var query = #"INSERT INTO [dbo].[Users]
([CompanyId],[EmployeeId]) VALUES (3,#emplid)";
context.Database.ExecuteSqlCommand(query, new SqlParameter[] {
new SqlParameter("emplid", u.EmployeeId)});
I have tried to access the Users list on the Company object. That does not work.
I have tried to use context.Users.Create() instead of new User(). Does not change anything.
I have tried to inject SQL, still the same problem. That exact SQL works, if ran from the Studio Manager.
I have tried to context.SaveChanges() after each add, nothing changed.
I know for a fact that the state of the entity about to be added is correct, also in the cases where CompanyId is set to NULL.
Could there be something with my underlying database?
Thank you so much for your time and help!
Try the following:
foreach (var u in usersFromFile) {
if (context.Users.Any(
user=>
user.EmployeeId == u.EmployeeId && user.CompanyId == 1)
)
{
User newUser = new User();
newUser.EmployeeId = u.EmployeeId;
newUser.CompanyId = 1;
context.Users.Add(newUser); //This will sometimes set CompanyId = NULL
}
}
context.SaveChanges();
The Any() function checks wether a user based on the given query exists.
Also, don't forget to add the context.savechanges to make sure every added record gets put in the database.
Lastly, you checked if user.CompanyId = 1, should be == 1
I ended up transforming the list of users to a series of SQL statemens, and running them through context.Database.ExecuteSqlCommand(sql).
It's dirty but it works.
If anyone has any good ideas as to why the FK CompanyId on the user entity is sometimes set to NULL I'd we very happy if you share your ideas.
Related
I have a webpage and a gridview connected to a database table. My update queries of the columns are as followed:
if (oldName != NAME && oldCreated == DATE)
{
GeneralDbExecuterService.executeSqlNonQuery(string.Format("UPDATE EXCEPTIONAL_USE_POLICY_PARAM SET NAME = '{0}' WHERE ID = '{1}' ", NAME, ID));
}
// if date was changed alone
if (oldCreated != DATE && oldName == NAME)
{
GeneralDbExecuterService.executeSqlNonQuery(string.Format("UPDATE EXCEPTIONAL_USE_POLICY_PARAM SET CREATED_DATE = to_date('{0}', 'dd/MM/yyyy') WHERE ID = '{1}' ", DATE, ID));
}
// if both values were changed
if (oldName != NAME && oldCreated != DATE)
{
GeneralDbExecuterService.executeSqlNonQuery(string.Format("UPDATE EXCEPTIONAL_USE_POLICY_PARAM SET NAME = '{0}', CREATED_DATE = to_date('{2}', 'dd/MM/yyyy') WHERE ID = '{1}' ", NAME, ID, DATE));
}
My question is, how can I make it more modular?
For example if 2 more columns are added its going to raise my IFs by few if not dozens. What is the best way to achieve that kind of dynamic approach? And is that even possible?. Thanks
edit: my main goal is to be able to detect what/where change has happened, and query the specific columns/values . ( basically its what I did) im just asking if theres a better way because if I were to add 5 more columns, I'd end up adding 40 more if statements..
If you use Entity Framework, rather than raw SQL, then you won't need to have any if statements at all. Your method would take an entity, and your code would just get the existing entity out of the database, and set the properties from the incoming one, irrespective of whether or not they have changed (air code, assumptions made about how you set up your model, etc)...
private async Task Update(PolicyParam p) {
PolicyParam existing = await dbContext.PolicyParams.Single(pp => pp.Id == p.Id);
existing.Date = p.Date;
existing.Name = p.Name;
// Update other properties here
await dbContext.SaveChangesAsync();
}
If you add another column, you just add one more line of code above.
EF has a zillion other benefits, like cleaner code, less chance of SQL injection, etc.
I'm trying to make works a login functionality but for some users Linq return some values as null when they have a correct value in database. For other users everything works ok.
This is my linq
public Clientes Login(string username)
{
DataClasses1DataContext db = new DataClasses1DataContext();
var query = from c in db.Clientes
where c.NroDocumento == username
select c;
return query.FirstOrDefault();
}
Then in the service layer I have the following:
Clientes o = userData.Login(username);
return (o != null && password == o.Password)
? new UserEntity(o.CodCliente, o.Email, o.Empresa)
: null;
But when I debug, for some users I can see that the property o.Password has a value, and for others it appears as null.
The users are being created by other systems, so I don't know if that can impact, but when I run the Select directly in SQL Server, both users has a Password, so I don't understand which is the difference that makes Linq return null.
This is the image of the model (sorry for the spanish)
As per the comments it looks like there are duplicates, but some of them don't have a password. As you're using 'FirstOrDefault' in some cases it's picking up the one without a password.
I am trying to use a query to find the last ID (entry) in the table called ContributorUser in the database FPTContributorUsers and then add in a new entry thus assigning it the next available ID.
the below code allows me to add data to the table in the database however when I run it the ID (new entry to the table) shows as 0 and not 4. because I currently have three entries in my table
[HttpPost]
public ActionResult AddContributor(ContributorUsers AddCont)
{
if (AddCont.UserID == null)
{
throw new HttpException(404, "Please enter a valid RacfId");
}
else
{
FPTContributorUsers NewUser = new FPTContributorUsers();
NewUser.UserID = AddCont.UserID;
NewUser.ID = AddCont.ID;
db.ContributorUsers.Add(NewUser);
db.SaveChanges();
return RedirectToAction("index");
}
}
Have you thought about just making that the primary key and having it auto increment so you don't need to determine what it is yourself? That's usually the best way to go about handling actual ID's in my experience.
To do this in SQL Server follow these steps
To do this in MySQL follow these steps
As a note, if you do this you will need to update your EF model.
The other way to do it if you can't edit the database is to use MAX() for that column which will return the highest ID value, then just add one to it, no EF model updating required.
Try removing the "NewUser.ID = AddCont.ID" line and wait to get the NewUser.ID until after "db.SaveChanges()"
else
{
FPTContributorUsers NewUser = new FPTContributorUsers();
NewUser.UserID = AddCont.UserID;
db.ContributorUsers.Add(NewUser);
db.SaveChanges();
return RedirectToAction("index");
}
If the NewUser.ID property is an Identity Field in the database, it will not get populated until after the record is created during the SaveChanges() transaction commit.
Try Reload() the DB Context after SaveChanges() before you call the NewUser.ID so that the context is up-to-date
In my asp.net application I have two pages like new students and edit students. On the new student page I am passing general details like first name, last name, mobile number, email and register number.
Here RegNo should be unique. I am using Entity Framework for database connection. I'm checking with the condition to avoid the same RegNo being entered, like:
DataObject.Entities dataEntities = new DataObject.Entities();
if (!dataEntities.Students.Any(s => s.RegNo == RegNo))
{
// my code here.
}
The same way for edit option, when try to change the RegNo. If it is allotted to some other student, it should not go into the update code.
I know if I use the same condition here, it will fail, because the RegNo is there in the database for this student (the one am trying to update), so if the RegNo is allotted for this particular student and not for other students it should be accepted, otherwise should go to else part.
I don't know how to check this using Entity Framework. Can anyone help me,please?
I've a column StudentId, it's an autoincrement column
I tried like
if (!dataEntities.Students.Any(s => s.RegNo == RegNo && s.StudentId != StudentId))
{
}
still it's not working.....
if(!dataEntities.Students.Any(s=>s.RegNo == RegNo && s != studentBeingUpdated))
Replace studentBeingUpdated with a variable containing a reference to the student that you are currently updating.
you can set in database level.. ie if you set auto increment then you dont need to edit/ reassign id to someone else and there is no need for separate management for this.
Please tell me if i understood mistakenly. :)
I just declared an object for the student table and tried like,
DataObject.Student student = dataEntities.Students.First(s => s.StudentId ==
StudentId);
if (!dataEntities.Students.Any(s => s.RegNo == RegNo &&
s.StudentId != student.StudentId))
{
}
else
{
throw new exception("RegNo already exists!");
}
and its working for me
Currently, I'm developing an application that depends on (and thus connects to) various databases via LINQ-to-SQL. For one of the databases, the connection string may vary and is thus configurable - however, the schema of this database is identical for all connection strings.
Because of the configurable connection string, I want to validate the DataContext during the startup of my application, to make sure that all tables and views my application uses, are available.
The Table<T> objects in the DataContext object are always initialized - even if the corresponding SQL table or view doesn't have any records.
So then. Currently, the validation check is performed as follows:
bool valid = _dataContext.Articles.Count() > 0
&& _dataContext.Customers.Count() > 0
&& _dataContext.Orders.Count() > 0;
While this does work, the determination of the value of valid takes quite some time (every record of each Table is touched), which ultimately results in a time out. So, is there a faster, more reliable way to determine whether or not a Table<T> of a certain DataContext really exists as a table in the corresponding database?
Here is an (untested) idea:
Grab the name of your table. You can hard code it in, or you can grab it programmatically via
TableAttribute attribute = (TableAttribute)typeof(MyTableObject)
.GetCustomAttributes(typeof(TableAttribute), true)
.Single();
string name = attribute.Name;
MyTableObject is the LINQ-to-SQL generated object contained in your Table, i.e., the generic parameter T in Table<T>.
(TableAttribute is in System.Data.Linq.Mapping.)
Use the DataContext.ExecuteQuery method as in
var db = new MyDataContext();
var results = db.ExecuteQuery<string>("SELECT name FROM dbo.sysobjects WHERE xtype = 'U'");
bool hasTable = results.Any(s => "dbo." + s == name);
A slight change on Jason's answer (I gave him an upvote :))
public bool TableExistsInDatabase<T>()
{
TableAttribute attribute = (TableAttribute)typeof(T)
.GetCustomAttributes(typeof(TableAttribute), true)
.Single();
var result = ExecuteQuery<bool>(
String.Format(
"IF OBJECT_ID('{0}', 'U') IS NOT NULL
SELECT CAST(1 AS BIT) ELSE
SELECT CAST(0 AS BIT)", attribute.Name));
return result.First();
}