Наследование класса Linq to SQL и приведение результата запроса linq

StackOverflow https://stackoverflow.com/questions/494884

Вопрос

Я пишу приложение, в котором нам нужно будет расширить базовую сущность на ряд различных объектов (например, сотрудник, транспортное средство и т.д.).Дизайн таков, что существует таблица сущностей и вторая таблица со значениями, зависящими от типа, например, у сотрудника будет идентификационный номер, а у транспортного средства будет регистрационный номер.

Я унаследовал объект класса, созданный в контексте данных, но у меня возникли проблемы с приведением в моем репозитории.Каков правильный способ сделать это?

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

}

Затем в моем репозитории (ничего не наследует)

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

Приведение завершается неудачей в единственном методе, и, следовательно, я получаю обратно null.Насколько я понимаю, вы не можете определить явные или неявные операторы из базового класса или для базового класса?Как я могу получить результат Linq базового класса для приведения к унаследованному классу Employee, сохраняя при этом его состояние базы данных, чтобы я мог отправлять изменения?

Это было полезно?

Решение

С LINQ-to-SQL может работать наследование двумя способами:

  • дискриминатор по одной таблице (не подходит, поскольку ваши данные неоднородны)
  • базовый класс / мультитаблица (не то чтобы это не поддерживалось в dbml - только если вы пишете классы вручную)

LINQ-to-SQL не поддерживает наследование нескольких таблиц (т.е.один объект с данными из нескольких таблиц).Entity Framework делает это, но является более сложным;вы используете .Cast<T> и .OfType<T> в EF для приведения / фильтрации на основе подтипов.

Возможно, вы захотите взглянуть на:

Какова цель базового класса здесь?Если это добавляет поведение, то вы можете отредактировать dbml, чтобы указать общий базовый класс для всех ваших сущностей.Если у него есть свойства данных тогда это становится еще сложнее.

Лично я просто не стал бы делать это таким образом...Я бы сохранил отдельные классы для разных типов и правильно использовал контекст данных, используя отдельные таблицы для каждого типа:

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

Итак, не могли бы вы пояснить, что cAccountEntity есть ли здесь?

Другие советы

Спасибо за информацию, рассмотрю некоторые предложения...

Идея создания учетной записи entity заключалась в том, что на данный момент сайту нужно обрабатывать только сотрудников, но в будущем они могут захотеть добавить в систему транспортные средства и т.д. Система используется для присвоения затрат организации, поэтому для этой цели сотрудник обрабатывается так же, как транспортное средство.

Идея заключается в том, что сотрудник и транспортное средство должны обрабатываться одинаково для ссылок в базе данных и т.д., Но потребуется немного другая информация о них.Это сложный дизайн только потому, что они хотят добавить дополнительные типы позже, но без необходимости обновлять базу данных...

Однако в моем коде я хочу поговорить о employee, а не об общем типе объекта (сделать контроллер, представление и т.д. Намного проще в приложении mvc).Поскольку вы не можете предоставить определяемое пользователем приведение из базового класса в производный, я пропустил его наследование и вместо этого использовал следующее решение.Немного более громоздкий, но действительно работающий...Дайте мне знать, если кто-нибудь сможет найти лучший способ сделать это.

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

Как я могу получить результат Linq базового класса для приведения к унаследованному классу Employee

Это не подъем, это подавленность.

Я думаю, вы не понимаете приведение или, возможно, сравнение типа экземпляра и ссылочного типа.

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

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

Система.Исключение InvalidCastException:Невозможно преобразовать объект типа "Животное" в объект типа "Зебра".

Точно так же у вас есть экземпляр Entity, который вы не можете отключить, чтобы использовать для него ссылку на Employee.

Вы могли бы преобразовать типы, но тогда вам придется указать метод преобразования.

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();
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top