Domanda

Sto scrivendo un'applicazione in cui avremo bisogno di estendere un'entità di base in una serie di cose diverse (ad es. dipendente, veicolo ecc.). Il design è tale che esiste una tabella Entity e una seconda tabella con valori specifici del tipo, ad esempio un dipendente avrà un numero ID ma un veicolo avrà un numero di immatricolazione.

Ho ereditato dall'entità di classe generata nel contesto dei dati ma sto riscontrando problemi con il casting nel mio repository. Qual è il modo corretto di farlo?

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

}

Quindi nel mio repository (non eredita nulla)

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

Il cast fallisce nel singolo metodo e quindi torno indietro. È mia comprensione che non è possibile definire operatori espliciti o impliciti da o verso una classe base? Come posso ottenere il risultato Linq della classe base da trasmettere alla classe Employee ereditata, pur mantenendo il suo stato db in modo da poter inviare le modifiche?

È stato utile?

Soluzione

Con LINQ-to-SQL, ci sono due modi in cui l'ereditarietà può funzionare:

  • discriminatore su una singola tabella (non adatto poiché i tuoi dati non sono omogenei)
  • base-class / multi-table (non che questo non sia supportato nel dbml - solo se si scrivono le classi manualmente)

LINQ-to-SQL non supporta l'ereditarietà multi-tabella (ovvero un singolo oggetto con dati da più tabelle). Entity Framework lo fa, ma è più complesso; si utilizzano .Cast<T> e .OfType<T> in EF per trasmettere / filtrare in base ai sottotipi.

Potresti voler guardare:

Qual è lo scopo della classe base qui? Se aggiunge comportamento, è possibile modificare il dbml per specificare una classe base comune per tutte le entità. Se ha proprietà dei dati , diventa più complicato.

Personalmente, semplicemente non lo farei in questo modo ... Vorrei mantenere classi separate per i diversi tipi e utilizzare correttamente il contesto dei dati, usando le tabelle separate per 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);
}

Quindi - puoi chiarire cosa fa il cAccountEntity qui?

Altri suggerimenti

Grazie per l'input, esaminerò alcuni dei suggerimenti ...

L'idea alla base dell'entità account era che per ora il sito deve solo gestire i dipendenti, ma in futuro potrebbero voler aggiungere veicoli ecc. al sistema, il sistema viene utilizzato per assegnare i costi a un'entità, quindi a questo scopo un dipendente viene gestito come un veicolo.

L'idea è che un dipendente e un veicolo devono aver gestito lo stesso per fare riferimento nel db ecc. ma avranno bisogno di informazioni leggermente diverse su di loro. È un design complesso solo perché vogliono aggiungere altri tipi in seguito, ma senza dover aggiornare il db ...

Nel mio codice, tuttavia, voglio parlare di un dipendente non di un tipo di entità generico (rendere il controller, visualizzare ecc. molto più semplice in un'app mvc). Poiché non è possibile fornire un casting definito dall'utente dalla base alla classe derivata, ho saltato ereditandolo e invece ho utilizzato la seguente soluzione. Un po 'più ingombrante ma funziona ... Fammi sapere se qualcuno può vedere un modo migliore per farlo.

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

Come posso ottenere il risultato Linq della classe base da trasmettere alla classe Employee ereditata

Non è un upcast, è un downcast.

Penso che tu non capisca il casting o possibilmente - tipo di istanza vs tipo di riferimento.

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

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

System.InvalidCastException: impossibile eseguire il cast di oggetti di tipo 'Animale' per digitare 'Zebra'.

Allo stesso modo, si dispone di un'istanza di Entity che non è possibile effettuare il downcast per utilizzare un riferimento Employee contro di essa.

Potresti convertire i tipi, ma poi devi fornire un metodo di conversione.

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();
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top