I create a DNN(version 6.*) Module with LINQ to SQL. it was work by select operation and return true value, but in manipulate operation (update, insert, delete) when call SubmitChange() it not work:
SecurityLog dal = new SecurityLog()
{
Date = info.Date,
Description = info.Description,
UserIP = info.UserIP,
UserName = info.UserName
};
MyLogDataContext.CBI_SecurityLogs.InsertOnSubmit(dal);
MyLogDataContext.SubmitChanges();
although when i call SP binded method in DataContext it work complete.
MyLogDataContext.InsertSecurityLog(info.Date, info.UserName, info.Description, info.UserIP)
why it not work correct?
I don't see a Primary Key in your table. Linq needs a Primary Key defined to work.
Related
I am working on Entity framework with database first approach and I came across below issue.
I have a Customer table with columns col1, col2, col3 ,....,col8. I have created an entity for this table and this table has around 100 records already. Out of above 8 columns, col4 is marked as Non-null.
Class Customer
{
member col1;
member col2;
member col3;
member col4;
.
.
member col8;
}
class Main
{
//main logic to read data from database using EF
Customer obj = object of Customerwith values assigned to col1,col2 and col3 members
obj.col2=some changed value.
DBContext.SaveChanges(); //<- throws an error stating it is expecting value of col4.
}
In my application, I am trying to read the one of the record using the stored procedure using EF and stored procedure only returns col1,col2 and col3.
I am trying to save the modified value of col2 and trying to save back to database using DBContext. But it thows an error stating value of required field col4 is not provided.
FYI: I have gone through couple of forums and question and option to go with disabled verfication on SaveChanges is not feasible for me.
Is there any other way through which I can achieve partial update?
I guess EntityFramework.Utilities satisfies your conditions.
This code:
using (var db = new YourDbContext())
{
db.AttachAndModify(new BlogPost { ID = postId }).Set(x => x.Reads, 10);
db.SaveChanges();
}
will generate single SQL command:
exec sp_executesql N'UPDATE [dbo].[BlogPosts]
SET [Reads] = #0
WHERE ([ID] = #1)
',N'#0 int,#1 int',#0=10,#1=1
disabled verfication on SaveChanges is not feasible for me
Sure it is. You even have to disable validation on Save. But then you can't mark the whole entity as modified, which I think you did. You must mark individual properties as modified:
var mySmallCustomer = someService.GetCustomer(); // from sproc
mySmallCustomer.col2 = "updated";
var myLargeCustomer = new Customer();
context.Customers.Attach(myLargeCustomer);
Entry(myLargeCustomer).CurrentValues.SetValues(mySmallCustomer);
// Here it comes:
Entry(myLargeCustomer).Property(c => c.col2).IsModified = true;
context.Configuration.ValidateOnSaveEnabled = false;
context.SaveChanges();
So you see it's enough to get the "small" customer. From this object you create a stub entity (myLargeCustomer) that is used for updating the one property.
During a migration how do i Insert into my table, then retrieve the ID, and then use it to insert a related data in another table.
what i have now is an hardoced ID to insert, but I don't know what it's gonna be when i'll run the migration.
var contactId = 2;
var phoneNumber = 2;
Insert.IntoTable("Contacts")
.WithIdentityInsert()
.Row(new
{
Id = contactId,
TimeZoneId = contact.TimeZoneId,
contact.CultureId,
Type = (byte)(int)contact.Type,
Email = contact.Email.ToString(),
EntityId = entityId
});
Insert.IntoTable("PhoneNumbers")
.WithIdentityInsert()
.Row(new
{
Id = phoneNumberId,
phone.Number,
Type = (byte)(int)phone.Type,
ContactId = contactId
});
I'd like to be able to retrieve the inserted ID and use it for the second insert instead of harcoding it.
I'm using SQL Server if it's any help...
I Thought this would be trivial, but seems like it's not, after googling for it, and not seing any answers here.
You are able to manually insert the Id by chaining .WithInsertIdentity() after your .Row() call.
This will let you keep it in memory for use within other objects as Foreign Keys. Unfortunately, FluentMigrator doesn't actually execute any SQL until after all code within the Up() or Down() methods finish executing.
I use Execute.Sql() with ##IDENTITY in sql-query for same cases
I'm facing a problem that when I set a field any value than empty, EF will update the database.
But, when I clear the field (input[text] empty), the matching field in DB won't update to NULL.
Here are the codes:
C#
var entidade = new Plantas { CodPlanta = vm.CodPlanta };
db.Plantas.Attach(entidade);
entidade.CodEstado = vm.CodEstado;
entidade.NomePlanta = vm.NomePlanta;
entidade.CEP = vm.CEP;
entidade.Telefone = vm.Telefone;
entidade.Fax = vm.Fax;
db.SaveChanges();
SQL generated by EF
exec sp_executesql N'update [dbo].[Plantas]
set [CodEstado] = #0, [NomePlanta] = #1, [CEP] = #3
where ([CodPlanta] = #4)
',N'#0 int,#1 varchar(200),#3 char(8),#4 int',
#0=26,
#1='ApiaĆ',
#2='Integrada',
#3='18320000',
#4=373
go
See that when vm.Telefone and vm.Fax, these fields won't show in UPDATE query. But if a put some value, they will.
Even if the fields have some value before.
If a put a breakpoint at db.Savechanges(), it will show entidade.Telefone = null. But it won't go to the generated query.
How can I force Entity Framework to set fields to null?
The reason is that EF will only save modified fields. So if the field was null before you attach the object, and you set it to null again, EF will not update the database.
The solution is pretty simple: set the field to something other than null before you attach the object, than modify it to null before you save it.
One caveat: if you have optimistic concurrency control on the field, you may have to read the record from the database instead of attaching an empty object. Alternatively, use one column for optimistic concurrency control, such as a version number or SQL Server timestamp column.
For example, say you have this problem with the CEP column. Then do:
var entidade = new Plantas { CodPlanta = vm.CodPlanta };
entidade.CEP = "fake old value";
db.Plantas.Attach(entidade);
entidade.CEP = vm.CEP;
db.SaveChanges();
I found that setting attached instance of entity to "Modified" works:
db.Entry(entidade) = EntityState.Modified;
db.SaveChanges();
I'm using EF 5 Database first approach in my MVC application. all of my tables uses a Field called Deleted which is a boolean field to mark a record is deleted.
I'm trying to get rid of the requirement of having to check Deleted == false every time I query my database. The very straightforward way of doing this is to use a conditional mapping in the edmx file where EF always return data that are not deleted. That's all good.
But the problem of doing this condition mapping is that, when I want to allow the user to delete some record for e.g Address from their address book I don't have access to Delete field from EF as I used it in the conditional mapping and therefore I have to look for another option to allow user to delete a record.
The way I thought is to create a stored proc that handle the delete query and call it when I want to delete the record.
Is there a better way of doing this? Is it possible to make the Delete field accessible even it is used in the conditional mapping?
I have a working solution for Soft Delete in Entity Framework Code First that may help.
The key is that you add a discriminator to every model that you want to be able to soft delete. In code first that is done like this:
modelBuilder.Entity<Foo>().Map(m => m.Requires("IsDeleted").HasValue(false));
This makes it invisible to the context and therefore you have to do the deletes using sql.
If this is the equivalent of your "conditional mapping" in Database First then one way to modify the sql is to override SaveChanges and run sql from there:
public override int SaveChanges()
{
foreach (var entry in ChangeTracker.Entries()
.Where(p => p.State == EntityState.Deleted
&& p.Entity is ModelBase))//I do have a base class for entities with a single
//"ID" property - all my entities derive from this,
//but you could use ISoftDelete here
SoftDelete(entry);
return base.SaveChanges();
}
private void SoftDelete(DbEntityEntry entry)
{
var e = entry.Entity as ModelBase;
string tableName = GetTableName(e.GetType());
Database.ExecuteSqlCommand(
String.Format("UPDATE {0} SET IsDeleted = 1 WHERE ID = #id", tableName)
, new SqlParameter("id", e.ID));
//Marking it Unchanged prevents the hard delete
//entry.State = EntityState.Unchanged;
//So does setting it to Detached:
//And that is what EF does when it deletes an item
//http://msdn.microsoft.com/en-us/data/jj592676.aspx
entry.State = EntityState.Detached;
}
Method used to Get Table Name explained here
That is the way I used to do it. Probably irrelevant to your Database First approach in EF5, but I have now moved to doing it in stored procedures. EF6 Code First generates CreateStoredProcedure calls in Migration files. I replace these with this.CreateDeleteProcedure("dbo.Foo_Delete", "[dbo].[Foos]"); - which is a call to my own extension method:
public static class MigrationExtensions
{
internal static string DeleteSqlFormat
{
//I also hard delete anything deleted more than a day ago in the same table
get { return "DELETE FROM {0} WHERE IsDeleted = 1 AND DATEADD(DAY, 1, DeletedAt) < GETUTCDATE(); UPDATE {0} SET IsDeleted = 1, DeletedAt = GETUTCDATE() WHERE ID = #ID;"; }
}
internal static void CreateDeleteProcedure(this DbMigration migration, string procName, string tableName)
{
migration.CreateStoredProcedure(
procName,
p => new
{
ID = p.Int(),
},
body:
string.Format(MigrationExtensions.DeleteSqlFormat, tableName)
);
}
}
I have the following function to update and insert a record in the table
public DASInput UpdateDASInputTable(DASInput fileSetData, Guid programID)
{
string connectionString = GetConnectionString(programID);
BI_ProgramConfigurationEntities dataContext = new BI_ProgramConfigurationEntities(connectionString);
dataContext.DASInputs.ApplyChanges(fileSetData);
dataContext.SaveChanges(System.Data.Objects.SaveOptions.DetectChangesBeforeSave);
fileSetData = dataContext.DASInputs.FirstOrDefault();
return fileSetData;
}
When I make first call with a new object of type DASInput, then it gets inserted correctly in the database. (DASInput table has the primary key as int with identity specification on).
But this first time insertion does not return the modified value of the primary key of the DASInput table.
So on every subsequent call a new record gets inserted in the database. I want the primary key(self generated by DB) to be returned to the client when the record gets inserted.
Isn't the syntax for adding an entity into a linq controlled database more along the lines of :
context.Table.AddObject(newStore);
//or
context.Table.Add(newStore);
context.SaveChanges();
I do answer this tentatively, not being hugely knowledgeable on LINQ.