Cómo guardar registros en dos tablas con relación 1 a 1 en EF 5

asi que estoy trabajando en esto ASP.NET MVC 4 proyecto y llego a este punto en el que creo que no puedo entender el problema. estoy usando Entity Framework 5 y Code first flujo de trabajo. Tengo esas dos entidades:

public class Document
{
    public int DocumentID { get; set; }
    public string Name { get; set; }
    public string Description
    public int UserFileID { get; set; }
    public UserFile UserFile { get; set; }
}

y respectivamente

public class UserFile
{
    public int UserFileID { get; set; }
    public string FileName { get; set; }
}

Ahora tengo una parte de administración donde permito que el administrador cree nuevos Document y la mayoría de las veces el usuario querrá agregar algún tipo de archivo al documento, pero quiero administrar los archivos cargados por el usuario por separado, así que tengo una entidad explícita donde planeo almacenar todos los archivos cargados.

Algo que parece muy estándar pero que realmente no puedo entender es esto:

Tengo una forma:

@using (Html.BeginForm("Documents", "Admin",
                    FormMethod.Post, new { enctype = "multipart/form-data" }))
{
    @Html.TextBoxFor(m => m.Name)
    @Html.TextBoxFor(m => m.Description)
    <input name="file" type="file" />
    <input type="submit" value="Upload File" id="btnSubmit" />
}

Luego, en mi Acción del controlador, me gustaría copiar el archivo y crear los registros en Document y UserFile pero no veo cómo se supone que debo hacerlo. Uso repositorios y UnitOfWork entonces en mi controlador podría primero:

UserFile item = new UserFile();
//take the name of the uploaded file and set it for item.Name
unitOfWork.UserFileRepository.Add(item);

Pero luego tengo que guardar el Document donde puedo comenzar de nuevo con:

Document entity = new Document();
entity.Name = model.Name;
entity.Description = model.Description;
entity.UserFile = ???
unitOfWork.DocumentRepository.Add(entity);

Lo que realmente no sé es cómo lidiar con la clave externa. Tengo un poco de experiencia, pero por lo que recuerdo en otros escenarios, solo necesito pasar el objeto de tipo UserFile me gusta:

var entityUserFile =  unitOfWork.UserFileRepository.GetById(Id);

y entonces:

entity.UserFile = entityUserFile;

Pero no veo una forma de obtener la ID del registro recién creado en UserFile mesa. Puedo pensar en una solución al establecer un nombre único para cada archivo, pero me preguntaba si hay alguna forma de lidiar con esto. Talvez algo Code First enfoque donde podría crear las dos instancias de entidad y dejar que Entity Framework se ocupe de establecer la relación, ¿tal vez de alguna otra manera? O estoy obligado a salvar el UserFile entidad entonces para recuperarlo y pasarlo como valor para mi Document ¿entidad?

preguntado el 03 de diciembre de 13 a las 13:12

1 Respuestas

¿Has probado esto?

UserFile item = new UserFile();
Document entity = new Document();
entity.Name = model.Name;
entity.Description = model.Description;
entity.UserFile = item;
unitOfWork.DocumentRepository.Add(entity);
unitOfWork.SaveChanges();

EL DbSet.Add() marca todos los objetos en el gráfico como "Agregados", por lo que el UserFile debe agregarse al mismo tiempo que Document.

Referencia:

¿Por qué Entity Framework reinserta objetos existentes en mi base de datos?

Alternativamente, EF debería arreglar su ID cuando guarde cambios (). Así que esto también debería funcionar:

UserFile item = new UserFile();
unitOfWork.UserFileRepository.Add(item);
unitOfWork.SaveChanges();//Database generates key 
                         //and EF fixes its in-memory version

Document entity = new Document();
entity.Name = model.Name;
entity.Description = model.Description;
entity.UserFileID = item.ID; //use the foreign key to avoid duplicate
unitOfWork.DocumentRepository.Add(entity);
unitOfWork.SaveChanges();

Es posible que desee adjuntar esto en TransactionScope porque ahora hay 2 llamadas a SaveChanges()

Respondido el 03 de diciembre de 13 a las 14:12

De hecho, después de que terminé de escribir aquí, probé lo que sugeriste, solo agregué item.FileName = "SomeName"; Y parece funcionar. De hecho, obtuve un registro en ambas tablas, por lo que funciona, pero no estoy completamente seguro de si esta es la forma correcta. ¿Crees que así es como se debe hacer este tipo de operación? No sé por qué pero no me gusta algo en este enfoque... - Lerón

Se agregó una versión alternativa que puede preferir: Colin

gracias por la respuesta. Tenía miedo de ir completamente en la dirección equivocada, no puedo decir que una sea preferible, tal vez si usted u otra persona pudiera decir cuál sería mejor usar: Lerón

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.