Pregunta

Estoy escribiendo una aplicación en la que vamos a necesitar extender una entidad básica en un número de cosas diferentes (por ejemplo, empleado, vehículo, etc).El diseño es tal que no existe una tabla de Entidad y una segunda tabla con el tipo de valores específicos, por ejemplo, un empleado tendrá un Número de IDENTIFICACIÓN, pero un vehículo tendrá un número de registro.

Me han heredado de la clase de entidad que se generan en el Contexto de los Datos, pero estoy teniendo problemas con el casting en mi repositorio.¿Cuál es la forma correcta de hacer esto?

public class cAccountEmployee : cAccountEntity
{
    public string id_number
    {
        get
        {
            try
            {
                return this.cAccountEntityValues.Single(e => e.type == 1).value;
            }
            catch (Exception)
            {
                return "";
            }
        }

        set
        {
            try
            {
                this.cAccountEntityValues.Single(e => e.type == 1).value = value;
            }
            catch (Exception)
            {
                this.cAccountEntityValues.Add(new cAccountEntityValue()
                                            {
                                                accountentity_id = this.id,
                                                cAccountEntity = this,
                                                type = 1,
                                                value = value
                                            });
            }
        }
    }

}

Luego, en mi repositorio (no hereda nada)

public IEnumerable<cAccountEmployee> All(int accountholder_id)
    {
        return db.cAccountEntities.Where(e => e.accountholder_id == accountholder_id).OrderBy(a => a.name).Cast<cAccountEmployee>();
    }

    public cAccountEmployee Single(int id)
    {
        return db.cAccountEntities.Single(a => a.id == id) as cAccountEmployee;
    }

La conversión falla en el método único y por lo tanto vuelvo a null.A mi entender, no se puede definir explícita o implícita de los operadores de o para una clase base?¿Cómo puedo llegar a la base de la clase de Linq resultado para emitir hasta el heredado de la clase Empleado, mientras que todavía mantiene su base de datos estatal para que yo pueda enviar los cambios?

¿Fue útil?

Solución

Con LINQ to SQL, hay dos formas de herencia puede trabajar:

  • discriminador sobre una sola tabla (no es la adecuada ya que sus datos no homogéneos)
  • la clase de base / multi-mesa (no es que este no es compatible con el dbml - sólo si se escribe manualmente las clases)

LINQ to SQL no soporta multi-mesa de la herencia (es decir,un solo objeto con los datos de varias tablas).Entity Framework hace, pero es más complejo;utiliza .Cast<T> y .OfType<T> en EF cast/filtro basado en sub-tipos.

Es posible que desee buscar en:

¿Cuál es el propósito de la clase base aquí?Si se añade el comportamiento, entonces usted puede editar el dbml para especificar una base común de clase para todas las entidades.Si tiene las propiedades de los datos a continuación, se pone más complicado.

Personalmente, yo simplemente no hacerlo de esta manera...Me gustaría seguir clases separadas para los diferentes tipos, y el uso de los datos de contexto correctamente, utilizando las tablas separadas por tipo:

public IEnumerable<Employee> All(int accountholder_id)
{
    return db.Employees.Where(e => e.accountholder_id == accountholder_id)
        .OrderBy(a => a.name);
}

public Employee Single(int id)
{
    return db.Employees.Single(a => a.id == id);
}

Así se puede aclarar lo que el cAccountEntity hace aquí?

Otros consejos

Gracias por el aporte, revisaremos algunas de las sugerencias ...

La idea detrás de la entidad de cuenta era que a partir de ahora el sitio solo necesita manejar a los empleados, pero en el futuro tal vez quieran agregar vehículos, etc. al sistema, el sistema se utiliza para asignar costos a una entidad, por lo que para este propósito un empleado se maneja igual que un vehículo.

La idea es que un empleado y un vehículo necesitan que él maneje lo mismo para hacer referencia en la base de datos, etc., pero necesitará información ligeramente diferente sobre ellos. Es un diseño complejo solo porque desean agregar tipos adicionales más adelante, pero sin necesidad de actualizar la base de datos ...

Sin embargo, en mi código quiero hablar sobre un empleado, no sobre un tipo de entidad genérico (hacer que el controlador, la vista, etc. sean mucho más fáciles en una aplicación mvc). Como no puede proporcionar una conversión definida por el usuario desde la base a la clase derivada, he omitido la herencia y utilicé la siguiente solución. Un poco más engorroso pero funciona ... Avíseme si alguien puede ver una mejor manera de hacerlo.

public class cAccountEmployee
{
    private cAccountEntity entity;

    public int id
    {
        get
        {
            return this.entity.id;
        }
        set
        {
            this.entity.id = value;
        }
    }

    public string name
    {
        get
        {
            return this.entity.name;
        }
        set
        {
            this.entity.name = value;
        }
    }

    public int accountholder_id
    {
        get
        {
            return this.entity.accountholder_id;
        }
        set
        {
            this.entity.accountholder_id = value;
        }
    }

    public System.Data.Linq.EntitySet<cAccountEntityValue> cAccountEntityValues
    {
        get
        {
            return this.entity.cAccountEntityValues;
        }
    }

    public cAccountHolder cAccountHolder
    {
        get
        {
            return this.entity.cAccountHolder;
        }
    }

    public cAccountEmployee()
    {
        this.entity = new cAccountEntity();
    }

    public cAccountEmployee(cAccountEntity entity)
    {
        this.entity = entity;
    }

    public string id_number
    {
        get
        {
            try
            {
                return this.entity.cAccountEntityValues.Single(e => e.type == 1).value;
            }
            catch (Exception)
            {
                return "";
            }
        }

        set
        {
            try
            {
                this.entity.cAccountEntityValues.Single(e => e.type == 1).value = value;
            }
            catch (Exception)
            {
                this.entity.cAccountEntityValues.Add(new cAccountEntityValue()
                                            {
                                                accountentity_id = this.id,
                                                cAccountEntity = this.entity,
                                                type = 1,
                                                value = value
                                            });
            }
        }
    }
}

//In the repository
public cAccountEmployee Single(int id)
    {
        return new cAccountEmployee(db.cAccountEntities.Single(a => a.id == id));
    }
  

¿Cómo puedo obtener el resultado de Linq de la clase base para convertirlo en la clase de empleado heredada?

No es un upcast, es un downcast.

Creo que no entiendes el casting o posiblemente el tipo de instancia frente al tipo de referencia.

public class Animal { }
public class Zebra : Animal { }

public class Zoo
{
    public void ShowZebraCast()
    {
        Animal a = new Animal();
        Zebra z = (Zebra)a;
    }
}

System.InvalidCastException: no se puede emitir un objeto de tipo 'Animal' para escribir 'Zebra'.

Del mismo modo, tiene una instancia de Entidad que no puede rechazar para usar una referencia de Empleado en su contra.

Puede convertir los tipos, pero luego debe proporcionar un método de conversión.

public partial class Animal { }
public class Zebra : Animal { }
//in another file
public partial class Animal{
  public Zebra ToZebra(){
    return new Zebra() { //set Zebra properties here.
    };
  }
}


public class Zoo
{
    public void ShowZebraConvert()
    {
        Animal a = new Animal();
        Zebra z = a.ToZebra();
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top