I'm using entity framework for first time. I have to create many entities(tables) with using of Entity Framework 6, is there any way how automatically create history table for all the entities and insert old version of a row into EntityHistory table whenever is row changed?
If i am not wrong we can manage it With the help of Entity Framework Snapshot History.
Click here to view the similar answer.
Disclaimer: I'm the owner of the project Entity Framework Plus
Documentations: EF+ Audit
This library allows you to audit & save information in a database with the AutoSavePreAction Action.
AuditManager.DefaultConfiguration.AutoSavePreAction = (context, audit) =>
// ADD "Where(x => x.AuditEntryID == 0)" to allow multiple SaveChanges with same Audit
(context as EntityContext).AuditEntries.AddRange(audit.Entries);
// using Z.EntityFramework.Plus; // Don't forget to include this.
var ctx = new EntityContext();
// ... ctx changes ...
var audit = new Audit();
audit.CreatedBy = "ZZZ Projects"; // Optional
ctx.SaveChanges(audit);
// Access to all auditing information
var entries = audit.Entries;
foreach(var entry in entries)
{
foreach(var property in entry.Properties)
{
}
}
Related
I am making a simple editor on a web server that lets user change/add data to a single table stored on a MS SQL server.
I am using Entity Framework 6 to do this, and I am wondering how I should do to track the changes made to the entity model.
I would have hoped that I could load new data in the context, and have the context automatically diff against what's in the DB, and then call SaveChanges().
But from what I read online, it looks like I need to loop through all the data, and check myself what changed, so that I can then call Context.Entry(myEntry).State = Added or Context.Entry(myEntry).State = Modified
Is there no way for EF to automatically detect what's new, what's modified and what's unchanged?
I would recommend passing ViewModels or DTOs to the view, then map them back to the reloaded entity on a commit. EF will automatically only update values that change when setting values. Setting a value without changing the value will not trigger an update. (Where attaching an entity, and setting it's modified state will update all columns) Passing entities, while convenient, exposes more about your data structure than your UI may present, and can be tampered with before being sent back. Never trust anything coming back from the client. When serialized to a client, the data is no longer an entity, it is a JSON block of data. When sent back to the server, it isn't a tracked entity, it is a POCO with the entity's signature. No change tracking that EF entities can provide will apply on the client or survive serialization/deserialization.
For example:
Given a Child that has a name and birth date. We select a DTO to pass to the view. The view changes a name, we get the DTO back and copy all values, modified or otherwise back into the entity and call SaveChanges()
// For example, loading the child in the controller to pass to the view...
ChildDTO childDto = null;
using (var context = new TestDbContext())
{
childDto = context.Children
.Select(x => new ChildDto
{
ChildId = x.ChildId,
Name = x.Name,
BirthDte = x.BirthDate
}).Single(x => x.ChildId == 1);
}
// View updates just the name...
childDto.Name = "Luke";
// Example if the view passed DTO back to controller to update...
using (var context = new TestDbContext())
{
var child = context.Children.Single(x => x.ChildId == 1);
child.Name = childDto.Name;
child.BirthDate = childDto.BirthDate;
context.SaveChanges();
}
If the name changed and the birth date did not, the EF generated update statement would only update the Name. If the entity name was already "Luke", then no Update statement would be issued. You can verify this behavior with an SQL profiler to see if/when/what SQL EF sends to the database.
Automapper can help simplify this for getting the DTO back into the entity:
var mappingConfig = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Child, ChildDTO>();
cfg.CreateMap<ChildDTO, Child>();
});
Then when reading, leverage ProjectTo instead of Select:
using (var context = new TestDbContext())
{
childDto = context.Children
.ProjectTo<ChildDTO>(mappingConfig)
.Single(x => x.ChildId == 1);
}
... and when updating the entity:
using (var context = new TestDbContext())
{
var child = context.Children.Single(x => x.ChildId == 1);
var mapper = mappingConfig.CreateMapper();
mapper.Map(childDto, child); // copies values from DTO to the entity instance.
context.SaveChanges();
}
It's important to validate the DTO prior to copying values across to the Entity, whether doing it manually or with Automapper. Automapper config can also be set up to only copy over values that are expected/allowed to change.
Using .NET Core 2.2 and Entity Framework what is the easiest way to copy a database table to a new database table.
i.e. creating an archive copy of that table.
I suggest using raw sql in EntityFrameworkCore to accomplish what you need.
dbContext.Database.ExecuteSqlCommand(TransactionalBehavior.DoNotEnsureTransaction,
"INSERT INTO TABLE2
SELECT * FROM TABLE1" );
if memory is not an issue
var sourceFiles = _context.SourceTables.ToList();
foreach(var sourceFile in sourceFiles)
{
//if matching entity
_context.DestinationTables.Add(sourceFile);
//if not matching
var destination = new DestinationEntity
{
Prop1 = sourceFile.Prop1,
//other properties
}
_context.DestinationTables.Add(destination);
//if need to remove
_context.SourceTables.Remove(sourceFile);
}
_context.SaveChanges();
Help me please resolve one problem.
I use Entity Framework for work with datebase.
My situation:
I have two tables which i need to fill. One of them must to contain identificator from the second table. Now I insert data to first table and make save changes. It give me identificator for the entity and I can to insert in second table the row with this identificator from first entity.
As a result, I have two save changes for my context. And I think that it's bad practice.
Code example:
var registration = new Registration()
{
//fill some properties
};
_registrationEntityService.Insert(registration);
context.SaveChanges();
var profile = new Profile()
{
//fill some properties
profile.RegId = registration.Id
};
_profileEntityService.Insert(profile);
context.SaveChanges();
How I can resolve this problem? Thanks.
EF assumes to use navigation properties like profile.Registration to resolve such problems:
var registration = new Registration()
{
//fill some properties
};
var profile = new Profile()
{
//fill some properties
profile.Registration = registration
};
context.SaveChanges();
Just ensure you generated the needed navigation property (it's generally based on foreign keys in your db). I highly recommend you to read any EF guide first http://www.entityframeworktutorial.net/EntityFramework5/add-entity-graph-using-dbcontext.aspx
I'm new to EF and I've only worked with EF 6. When I use it to access the data from a database that I have already designed I don't see any method that allows me to manipulate data. To solve this temporarily I created some stored procedures for adding, deleting and updating data.
I would like to know if what I am doing is the right way to manipulate data in EF or not. In case it is not the right way how can I do this using the built in features of EF6. MSDN said there is an add object but couldn't find it.
There have been some changes in the API. EF6 does not use ObjectContext anymore, it uses a DbContext. This can be generated from a Database Model, or created using a Model first approach.
Old syntax:
objectContext.AddToUsers(user);
is now:
dbContext.Users.Add(user);
Here are some basic samples:
insert:
using(var dbContext = new MyDbContext())
{
var user = new User { ID=1, Name="Test" };
dbContext.Users.Add(user); // Add user
dbContext.SaveChanges(); // Save changes to DB
}
update:
using(var dbContext = new MyDbContext())
{
var user = dbContext.Users.Find(1);// find by ID = 1
user.Name = "New Name"; // Change name
dbContext.SaveChanges(); // Save changes to DB
}
delete:
using(var dbContext = new MyDbContext())
{
var user = dbContext.Users.Find(1);// find by ID = 1
dbContext.Users.Remove(user); // delete user
dbContext.SaveChanges(); // Save changes to DB
}
So, no need for stored procedures.. definetly not needed for simple CRUD.
Hi I use C# and EF 4.
I have two Entities CmsContent and CmsJob.
CmsJob has a navigational property to CmsContent.
I need add a CmsContent Object to CmsJob using the navigational property.
My code run with no error but I cannot persist the new entry om DataBase.
Could you tell me what I'm doing wrong?
Please provide me an example of code. Thanks for your support!
using (CmsConnectionStringEntityDataModel context = new CmsConnectionStringEntityDataModel())
{
CmsContent myContent = context.CmsContents.FirstOrDefault(x => x.ContentId == contentId);
CmsJob myJob = context.CmsJobs.FirstOrDefault(x => x.JobId == jobId);
myJob.CmsContents.Add(myContent);
}
Based on comments under #Hasan's answer you have incorrectly defined database. Your Job and Content are in many-to-many relation so you have junction table called CmsJobsContents but this table is missing primary key. Because of that it is read-only for EF and you cannot create new relations in your application. You must go to your database and mark both FKs in the CmsJobsContents as primary keys. After that update your model from database and you should be able to save changes.
That's because you haven't saved changes. Try this:
using (CmsConnectionStringEntityDataModel context = new CmsConnectionStringEntityDataModel())
{
CmsContent myContent = context.CmsContents.FirstOrDefault(x => x.ContentId == contentId);
CmsJob myJob = context.CmsJobs.FirstOrDefault(x => x.JobId == jobId);
myJob.CmsContents.Add(myContent);
context.SaveChanges();
}