EntityFramework Core - copy an object and return it to the database

Is there a best practice for copying a copy of an object, making any changes to it based on user input, and then reinstalling it in the database?

Some other Stackoverflow threads mentioned that EF will handle inserting new objects for you, even if the same primary key exists in the database, but I'm not quite sure how this works with EF Core. Whenever I try to copy an object, I get an error

Cannot insert explicit value for identity column in table when IDENTITY_INSERT is set to OFF

Basically, I just need a clean way to copy an object, make some changes to it based on user input, and then paste that copy back into the database and set up Id auto-increment correctly. Is there any best practice or an easy way to do this without having to manually set the properties to null or empty?

EDIT: sample code for retrieving an object from a database:

    public Incident GetIncidentByIdForCloning(int id)
    {
        try
        {
            return _context.Incident.Single(i => i.IncidentId == id);
        }
        catch
        {
            return null;
        }
    }

Code after retrieving the object (since some fields are automatically generated, for example, RowVersion, this is a timestamp):

public IActionResult Clone([FromBody]Incident Incident)
    {
        var incidentToCopy = _incidentService.IncidentRepository.GetIncidentByIdForCloning(Incident.IncidentId);
        incidentToCopy.IncidentTrackingRefId = _incidentService.IncidentRepository.GetNextIdForIncidentCategoryAndType(
            Incident.IncidentCategoryLookupTableId, Incident.IncidentTypeLookupTableId).GetValueOrDefault(0);
        incidentToCopy.RowVersion = null;
        incidentToCopy.IncidentId = 0; //This will fail with or without this line, this was more of a test to see if manually setting would default the insert operation, such as creating a brand new object would normally do.
        incidentToCopy.IncidentCategoryLookupTableId = Incident.IncidentCategoryLookupTableId;
        incidentToCopy.IncidentTypeLookupTableId = Incident.IncidentTypeLookupTableId;
        var newIncident = _incidentService.IncidentRepository.CreateIncident(incidentToCopy);
...

I understand that I can just make a completely new object and do left copy, but it seems terribly inefficient, and I want to know if EF Core offers the best solutions.

+4
3

, " " , -, , , - , , , , - . :

try
{
    var incidentToCopy = _context.Incident.Single(i => i.IncidentId == id);
    return (Incident) _context.Entry(incidentToCopy).CurrentValues.ToObject();
}
+4

IncidentRepository Incident AsNoTracking, , .

public void Clone(int id)
{
    // Prevent tracking changes to the object.
    var incident = _context.AsNoTracking().SingleOrDefault(i => i.Id == id);

    // Setting back to 0 should treat the object Id as unset.
    incident.Id = 0;

    // Add the Incident while it is untracked will treat it as a new entity.
    _context.Incidents.Add(incident);
    _context.SaveChanges();
}
+3

, :

,

context.ChangeTracker.Entries<Incident>

. id , , ChangeTracker . ChangeTracker , . , - ChangeTracker , id 0, context.DbSet, , , , .

0

Source: https://habr.com/ru/post/1675515/


All Articles