简体   繁体   English

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

[英]Inheriting a Linq to SQL class and cast the result of a linq query

I am writing an application where we will need to extend a basic entity into a number of different things (eg employee, vehicle etc). 我正在编写一个应用程序,我们需要将基本实体扩展为许多不同的东西(例如员工,车辆等)。 The design is as such that there is a Entity table and a second table with type specific values eg an employee will have an ID Number but a vehicle will have a registration number. 设计是这样的,即存在实体表和具有类型特定值的第二表,例如,雇员将具有ID号但车辆将具有注册号。

I have inherited from the class entity generated in the Data Context but am having trouble with the casting in my repository. 我继承了数据上下文中生成的类实体,但是在我的存储库中进行转换时遇到了问题。 What is the correct way of doing this? 这样做的正确方法是什么?

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

} }

Then in my repository (does not inherit anything) 然后在我的存储库中(不继承任何东西)

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

The cast fails in the single method and hence I get back null. 转换在单个方法中失败,因此我返回null。 It is my understanding you cannot define explicit or implicit operators from or to a base class? 我的理解是你无法从基类定义显式或隐式运算符? How can I get the base class Linq result to cast up to the inherited Employee class, while still maintaining its db state so I can submit changes? 如何才能将基类Linq结果转换为继承的Employee类,同时仍保持其db状态,以便我可以提交更改?

With LINQ-to-SQL, there are two ways inheritance can work: 使用LINQ-to-SQL,继承可以使用两种方式:

  • discriminator over a single table (not suitable since your data is not homogeneous) 单个表上的鉴别器(不合适,因为您的数据不是同质的)
  • base-class / multi-table (not that this isn't supported in the dbml - only if you write the classes manually) 基类/多表(不是dbml不支持这种情况 - 只有在手动编写类时)

LINQ-to-SQL does not support multi-table inheritance (ie a single object with data from multiple tables). LINQ-to-SQL不支持多表继承(即具有来自多个表的数据的单个对象)。 Entity Framework does, but is more complex; 实体框架确实如此,但更复杂; you use .Cast<T> and .OfType<T> in EF to cast/filter based on sub-types. 在EF中使用.Cast<T>.OfType<T>来根据子类型进行.OfType<T>转换/过滤。

You might want to look at: 你可能想看看:

What is the purpose of the base class here? 这里基类的目的是什么? If it adds behaviour, then you can edit the dbml to specify a common base-class for all your entities. 如果它添加了行为,那么您可以编辑dbml以指定所有实体的公共基类。 If it has data properties then it gets trickier. 如果它有数据属性,那么它会变得更加棘手。

Personally, I simply wouldn't do it this way... I would keep separate classes for the different types, and use the data-context correctly, using the separate tables per type: 就个人而言,我根本不会这样做...我会为不同类型保留单独的类,并正确使用数据上下文,使用每种类型的单独表:

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

So - can you clarify what the cAccountEntity does here? 那么 - 你能澄清一下cAccountEntity在这里做了什么吗?

Thanks for the input, will look over some of the suggestions... 感谢您的投入,将查看一些建议......

The idea behind account entity was that as of now the site only needs to handle employees but in the future they may want to add vehicles etc to the system, the system is used to assign costs to an entity, so for this purpose an employee is handled the same as a vehicle. 帐户实体背后的想法是,到目前为止,该网站只需要处理员工,但将来他们可能想要向系统添加车辆等,系统用于为实体分配成本,因此为此目的,员工是处理与车辆相同。

The idea being that an employee and a vehicle need to he handled the same for referencing in the db etc but will need slightly different info about them. 我们的想法是,员工和车辆需要处理同样的数据,以便在数据库等中进行引用,但需要稍微不同的信息。 It is a complex design only because they want to add extra types later but without needing to upgrade the db... 这是一个复杂的设计,只是因为他们希望以后添加额外的类型,但不需要升级数据库......

In my code however I want to talk about an employee not about a generic entity type (make controller, view etc much easier in an mvc app). 但是在我的代码中,我想谈谈一个员工而不是通用实体类型(在mvc应用程序中使控制器,视图等更容易)。 As you cannot supply a user-defined casting from base to derived class I have skipped inheritting it and used the following solution instead. 由于您无法提供从基类到派生类的用户定义的转换,因此我已跳过继承并使用以下解决方案。 Bit more cumbersome but does work... Let me know if someone can see a better way of doing this. 有点麻烦,但确实有用......如果有人能看到更好的方法,请告诉我。

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

How can I get the base class Linq result to cast up to the inherited Employee class 如何将基类Linq结果转换为继承的Employee类

It's not an upcast, it's a downcast. 这不是一个向上,它是一个沮丧。

I think you don't understand casting or possibly - instance type vs reference type. 我认为你不理解转换或可能 - 实例类型与引用类型。

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

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

System.InvalidCastException: Unable to cast object of type 'Animal' to type 'Zebra'. System.InvalidCastException:无法将“Animal”类型的对象强制转换为“Zebra”类型。

In the same way, you have an instance of Entity that you can't downcast to use an Employee reference against it. 以同样的方式,您有一个实体实例,您无法向下转换以使用针对它的Employee引用。

You could convert the types, but then you have to supply a conversion method. 您可以转换类型,但是您必须提供转换方法。

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 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM