继承Linq to SQL类并转换linq查询的结果

时间:2009-01-30 08:35:11

标签: c# linq inheritance casting base

我正在编写一个应用程序,我们需要将基本实体扩展为许多不同的东西(例如员工,车辆等)。设计是这样的,即存在实体表和具有类型特定值的第二个表,例如,员工将具有ID号,但车辆将具有注册号。

我从数据上下文中生成的类实体继承但是在我的存储库中的转换有问题。这样做的正确方法是什么?

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类,同时仍保持其db状态,以便我可以提交更改?

3 个答案:

答案 0 :(得分:1)

使用LINQ-to-SQL,继承可以使用两种方式:

  • 单个表上的鉴别器(不合适,因为您的数据不均匀)
  • 基类/多表(不是dbml不支持这种情况 - 只有手动编写类)

LINQ-to-SQL不支持多表继承(即包含来自多个表的数据的单个对象)。实体框架确实如此,但更复杂;您可以在EF中使用.Cast<T>.OfType<T>根据子类型进行投射/过滤。

您可能需要查看:

这里基类的目的是什么?如果它添加了行为,那么您可以编辑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在这里的作用吗?

答案 1 :(得分:0)

感谢您的投入,将会查看一些建议......

帐户实体背后的想法是,到目前为止,该网站只需要处理员工,但将来他们可能想要向系统添加车辆等,系统用于为实体分配成本,因此为此目的员工的处理方式与车辆相同。

这个想法是,员工和车辆需要处理相同的内容以便在数据库等中进行引用,但需要稍微不同的信息。这是一个复杂的设计,因为他们希望以后添加额外的类型,但不需要升级db ...

在我的代码中,我想谈谈员工不是关于通用实体类型(在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));
    }

答案 2 :(得分:0)

  

如何将基类Linq结果转换为继承的Employee类

这不是一个向上的人,而是一个沮丧的人。

我认为您不理解转换或可能 - 实例类型与引用类型。

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

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

System.InvalidCastException:无法将“Animal”类型的对象强制转换为“Zebra”类型。

以同样的方式,您有一个实体实例,您无法向下转换以使用针对它的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();
    }
}