Pregunta

He implementado alguna herencia de tabla por tipo en mi modelo de datos (básicamente tengo una BaseEntity escriba con toda la información base de mis artículos y un Employer tipo que hereda del BaseEntity artículo).Todo parece estar configurado correctamente y cuando uso las Entidades (ya sea a través de los Servicios de datos ADO.net o a través de Linq to Entities) puedo ver el Employer tipo y todo parece estar bien.El problema comienza cuando creo un nuevo Employer entidad e intentar salvarla.

Sobre el contexto que no parece ser un .AddToEmployer artículo (únicamente y AddObject o AddToBaseEntity).

si uso AddObject("Employer", NewEmployer) Recibo un mensaje de error de:

No se pudo encontrar el nombre de EntitySet 'DataEntities.Employer'.

si uso AddToBaseEntity(NewEmployer) Recibo un mensaje de error de:

No se puede determinar un pedido válido para operaciones dependientes.Pueden existir dependencias debido a restricciones de clave externa, requisitos del modelo o valores generados por la tienda.

¿Me he saltado algún paso en la preparación de la herencia?¿Existe alguna forma específica de guardar objetos heredados?¿Qué estoy haciendo mal?Supongo que la cuestión básica es que debería tener un AddToEmployer, ¿qué debo hacer para que eso quede expuesto?Parece extraño que no sea una opción ya que puedo ver el tipo de Empleador en el lado del cliente y puedo hacer cosas como:

var NewEmployer = new Employer() - lo que parece sugerir que puedo ver bien el tipo de Empleador.

¿Fue útil?

Solución 3

Cambié un par de cosas y pude hacer que esto funcione. No estoy particularmente seguro de cuál era el problema básico, pero quería publicar lo que hice como referencia.

Tablas reconstruidas: reconstruí las tablas comenzando solo con las columnas ID / Clave y una sola columna de datos.

Se eliminaron los campos adicionales de incremento automático: tenía una identificación de incremento automático en BaseEntity y en el Patrón. Eliminé el ID de incremento automático en el Empleador y acabo de tener la columna Employer.BaseEntityID y la clave foránea de regreso a BaseEntity.BaseEntityID. (esto parece haber sido el culpable, pero tenía la impresión de que esto estaba permitido)

Desafortunadamente, esto lleva a la cuestión de que las clases heredadas en el marco de la entidad no pueden tener propiedades de navegación (todas las propiedades de navegación deben estar en la entidad base), por lo que la herencia no será utilizable para nuestras necesidades.

Otros consejos

Mi nombre es Phani y trabajo en el equipo de Servicios de datos de ADO.NET.

El ResolveName y ResolveType Los métodos sirven para ayudarle a personalizar el tipo de información que el cliente escribe en la carga útil enviada al servidor y cómo se materializa la carga útil de respuesta del servidor.

Le ayudan a resolver tipos en el cliente y son útiles en muchos escenarios, un par de ejemplos son:

  1. La jerarquía de tipos de entidades en el cliente es diferente a la del servidor.
  2. Los tipos de entidad expuestos por el servicio participan en la herencia y desea trabajar con tipos derivados en el cliente.

ResolveName se utiliza para cambiar el nombre de la entidad que ponemos en el cable al realizar una solicitud al servidor.

Considere este modelo de datos:En el servidor

public class Employee {
    public int EmployeeID {get;set;}
    public string EmployeeName {get;set;}
}

public class Manager:Employee {
    public List<int> employeesWhoReportToMe {get;set;}
}

Cuando se utiliza el cliente para trabajar con instancias del tipo de entidad Manager , Al enviar los cambios al servidor, esperamos que la información de tipo esté presente en la carga útil cuando las entidades participen en la herencia.

context.AddObject("Employees",ManagerInstance ); <-- add manager instance to the employees set.
context.SaveChanges();

Sin embargo, cuando el cliente serializa esta carga, coloca "Empleado" como nombre de tipo que no es lo que se espera en el servidor.Por lo tanto, debe proporcionar un solucionador de nombres en el cliente,

context.ResolveName = delegate(Type entityType){
    //do what you have to do to resolve the type to the right type of the entity on the server
    return entityType.FullName;
}

un solucionador de tipos se utiliza de la misma manera.

context.ResolveType = delegate(string entitySetName){
    //do what you have to do to convert the entitysetName to a type that the client understands
    return Type.GetType(entitySetName);
}

Bueno, solo obtienes un conjunto de entidades pr. base class so .AddToBaseEntity es la solución como tal.

Pero parece que tiene una dependencia circular en su modelo, por lo que el marco de Entity no puede determinar en qué orden guardar.

Compruebe que tiene claves externas para la entidad base en sus entidades derivadas y actualice su modelo.

No tiene un Patrón definido como conjunto de entidades, al igual que el tipo de entidad. Esa es la forma en que falta AddToEntity en el objeto de contexto. Siempre hay un conjunto de entidades para una jerarquía de clases, en este caso es un conjunto de entidades BaseClass.

Si desea obtener el conjunto de entidades 'Empleador', puede intentar editar manualmente el archivo edmx y agregar un nuevo conjunto de entidades 'Empleador', y luego configurar el tipo de entidad 'Empleador' para que pertenezca a ese conjunto de entidades. No debería ser difícil, lo he hecho muchas veces.

No estoy seguro de si hay alguna solución más regular.

Más de dos años después, pero con el interés de mantenerlo relevante para el tráfico de búsqueda, he aquí una forma de solucionar esto rápidamente en una clase de conveniencia que estábamos usando para llenar rápidamente nuestra base de datos con datos de preparación.

No estoy seguro acerca de las versiones anteriores, pero Entity Framework 4 le permite volcar el objeto en el contexto como un objeto base, y luego el marco resuelve las referencias del lado del servidor. Por lo tanto, no usaría AddToInheritedObjects () (que de todos modos está en desuso) sino el método ObjectSet & Lt; & Gt; .Add ().

Aquí hay un ejemplo de clase auxiliar:

public ContextHelper
{
        …
        _context = ModelEntities();

        public T Create<T>() where T : class
        {
            // Create a new context
            _context = new ModelEntities();

            // Create the object using the context (can create outside of context too, FYI)
            T obj = _context.CreateObject<T>();

            // Somewhat kludgy workaround for determining if the object is
            // inherited from the base object or not, and adding it to the context's
            // object list appropriately.    
            if (obj is BaseObject)
            {
                _context.AddObject("BaseObjects", obj);
            }
            else
            {
                ObjectSet<T> set = _context.CreateObjectSet<T>();
                set.AddObject(obj);
            }

            return obj;
        }
        …
}

Por lo tanto, suponiendo que tenga lo siguiente:

class ObjectOne : BaseObject {}
class ObjectTwo {}

Puede agregar fácilmente entidades al contexto:

ContextHelper ch = ContextHelper()
ObjectOne inherited = ch.Create<ObjectOne>();
ObjectTwo toplevel = ch.Create<ObjectTwo>();
…

Recordando, por supuesto, que ContextHelper debería tener un método público Save () que llame a _context.SaveChanges (), o que debería tener alguna otra forma de enviar los cambios de objetos al almacén de datos.

Esto podría no ser una respuesta directa a una pregunta dada sobre la herencia, pero con suerte le da a las personas un punto de partida para responder detalles.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top