Pergunta

Eu estou escrevendo uma aplicação onde teremos de estender uma entidade básica para uma série de coisas diferentes (por exemplo, empregado, veículo etc). O design é como tal que há uma mesa Entidade e uma segunda tabela com valores específicos do tipo por exemplo, um funcionário terá um número de identificação, mas um veículo terá um número de registo.

Eu herdei da entidade de classe gerados no contexto de dados, mas estou tendo problemas com o elenco no meu repositório. O que é a maneira correta de fazer isso?

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
                                            });
            }
        }
    }

}

Em seguida, no meu repositório (não faz nada herdar)

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;
    }

O elenco falha no método único e, portanto, eu voltar nulo. É meu entendimento que você não pode definir operadores explícitos ou implícitos a partir de ou para uma classe base? Como posso obter o resultado Linq classe base para lançar-se para a classe Employee herdado, mantendo seu estado db para que eu possa enviar as alterações?

Foi útil?

Solução

Com LINQ to SQL, existem duas maneiras de herança pode trabalhar:

  • discriminador sobre uma única tabela (não é adequado uma vez que seus dados não é homogênea)
  • base-classe / multi-mesa (não que isso não é suportado no dbml - só se você escrever as classes manualmente)

LINQ to SQL não suporta herança multi-mesa (ou seja, um único objeto com dados de várias tabelas). Entity Framework faz, mas é mais complexo; você usa .Cast<T> e .OfType<T> na EF para lançar / filtro com base em sub-tipos.

Você pode querer olhar em:

Qual é o propósito da classe base aqui? Se ele adiciona comportamento, então você pode editar o dbml para especificar uma classe base comum para todas as suas entidades. Se ele tem propriedades dados , em seguida, torna-se mais complicado.

Pessoalmente, eu simplesmente não iria fazê-lo desta maneira ... Eu iria manter classes separadas para os diferentes tipos, e usar o contexto de dados corretamente, usando as tabelas 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);
}

Então? - você pode esclarecer o que o cAccountEntity faz aqui

Outras dicas

Obrigado pela contribuição, vai olhar sobre algumas das sugestões ...

A idéia por trás entidade conta foi que a partir de agora o site só precisa lidar com empregados, mas, no futuro, pode querer adicionar veículos, etc, para o sistema, o sistema é usado para os custos de atribuir a uma entidade, por isso para esta finalidade um empregado é tratado da mesma como um veículo.

A idéia é que um empregado e uma necessidade veículo para ele lidou com o mesmo para referência no db etc, mas vai precisar de informações ligeiramente diferente sobre eles. É um projeto complexo só porque querem adicionar tipos de extras mais tarde, mas sem a necessidade de atualizar o db ...

No meu código no entanto eu quero falar sobre um empregado não se trata de um tipo de entidade genérica (controlador de marca, ver etc muito mais fácil em um aplicativo MVC). Como você não pode fornecer um casting definido pelo usuário da base à classe derivada Eu ter pulado inheritting e usou a seguinte solução vez. Pouco mais pesado, mas não trabalho ... Deixe-me saber se alguém pode ver uma maneira melhor de fazer isso.

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));
    }

Como posso obter o resultado Linq classe base para lançar-se para a classe Employee herdado

Não é uma upcast, é um abatido.

Eu acho que você não entende fundição ou possivelmente -. Tipo de instância vs tipo de referência

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

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

System.InvalidCastException:. Não é possível para objeto fundido do tipo 'Animal' para digitar 'Zebra'

Da mesma forma, você tem uma instância de entidade que você não pode abatido usar uma referência do empregado contra ela.

Você pode converter os tipos, mas então você tem que fornecer um método de conversão.

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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top