【问题标题】:Inheriting a Linq to SQL class and cast the result of a linq query继承 Linq to SQL 类并转换 linq 查询的结果
【发布时间】:2009-01-30 08:35:11
【问题描述】:

我正在编写一个应用程序,我们需要将一个基本实体扩展到许多不同的事物(例如员工、车辆等)。设计是这样的,有一个实体表和一个具有特定类型值的第二个表,例如员工将有一个 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 状态以便我可以提交更改?

【问题讨论】:

    标签: c# linq inheritance casting base


    【解决方案1】:

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

    • 单个表的鉴别器(不适合,因为您的数据不是同质的)
    • 基类/多表(不是说这在 dbml 中不受支持 - 仅当您手动编写类时)

    LINQ-to-SQL 不支持多表继承(即单个对象具有来自多个表的数据)。实体框架可以,但更复杂;您在 EF 中使用 .Cast&lt;T&gt;.OfType&lt;T&gt; 根据子类型进行转换/过滤。

    你可能想看看:

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

    【讨论】:

      【解决方案2】:

      感谢您的意见,将查看一些建议...

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

      这个想法是员工和车辆需要他处理相同的数据库等引用,但需要关于它们的稍微不同的信息。这是一个复杂的设计,只是因为他们想稍后添加额外的类型,但不需要升级数据库......

      然而,在我的代码中,我想谈论的是员工而不是通用实体类型(使控制器、视图等在 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));
          }
      

      【讨论】:

        【解决方案3】:

        如何将基类 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”类型。

        以同样的方式,您有一个 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();
            }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-02-24
          • 1970-01-01
          • 2017-10-06
          • 2020-08-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多