I need to duplicate a Transport
entity (including child entities except one of them: Documents
which of type 'Mail').
Here is my model:
public class Transport
{
[Key]
public int Id { get; set; }
public string TransportNumber { get; set; }
...
public virtual List<Document> Documents { get; set; }
}
public class Document
{
[Key]
public int Id { get; set; }
public EnumDocumentType Type { get; set; }
public int FileId { get; set; }
public virtual File File { get; set; }
public virtual Transport Transport { get; set; }
}
public class File
{
[Key]
public int Id { get; set; }
public string Filename { get; set; }
public byte[] FileStream { get; set; }
}
My c# code for duplicating:
public void DuplicateTransports(IEnumerable<int> ids) {
var transportsToDuplicate = Context.Transports.Where(t => ids.Contains(t.Id))
.Include(c => c.Documents).ToList();
transportsToDuplicate.ForEach(t =>
{
var newTransport = Context.Transports.Add(t);
newTransport.Id = -100;
AttributeNumber(newTransport);
t.Documents.ForEach(doc =>
{
ObjectContext.LoadProperty(doc, x => x.File);
Context.Documents.Add(doc);
Context.Files.Add(doc.File);
});
Context.SaveChanges();
// (step 2) Don't duplicate child Documents of type Mail
var docs = Context.Documents.Where(doc => doc.TransportId == newTransport.Id && doc.Type == EnumDocumentType.Mail).ToList();
for (int i=docs.Count-1; i>=0; i--) Context.Documents.Remove(docs[i]);
Context.SaveChanges();
});
It works as expected but as you can see in the code, I had to proceed in 2 steps:
- step 1: duplicating element + save changes in the context
- step 2: searching for documents of type Mail and remove them + save changes in the context
My question: is it possible to proceed only in 1 step? So avoid adding in the context documents of type Mail because in my case I need to remove it at next step which I found not optimized.
Thanks.
EDIT
As suggested by Philip Stuyckx I already try to proceed in 1 step like this:
transportsToDuplicate.ForEach(t =>
{
var newTransport = Context.Transports.Add(t);
newTransport.Id = -100;
AttributeNumber(newTransport);
t.Documents.ForEach(doc =>
{
if (doc.Type != EnumDocumentType.Mail)
{
ObjectContext.LoadProperty(doc, x => x.File);
Context.Documents.Add(doc);
Context.Files.Add(doc.File);
}
});
Context.SaveChanges();
});
Then I got an exception: The changes to the database were committed successfully, but an error occurred while updating the object context. The ObjectContext might be in an inconsistent state. Inner exception message: A referential integrity constraint violation occurred: The property value(s) of 'Transport.Id' on one end of a relationship do not match the property value(s) of 'Document.TransportId' on the other end.