【问题标题】:Should a class have string fields for values from SQL JOIN from dictionary tables一个类是否应该具有来自字典表的 SQL JOIN 值的字符串字段
【发布时间】:2013-10-23 07:00:56
【问题描述】:

我有一个类(下面的代码)用于保存到数据库并从数据库中读取。一切正常,但是当最终打印从字典表中获取的一些对象信息时,我真的不知道将它们放在哪里。 (活动记录)。

类代码:

class Object
{
   public int id;
   public int size;
   public int color;
   public int author;

   public Object(int id, int size, int color, int author)
   {
      this.id = id;
      this.size = size;
      this.color = color;
      this.author = author;
   }

   // add, update, delete methods
}

所以对于上面的类,SQL:

从对象中选择id、大小、颜色、作者;

我是否应该将字符串字段添加到此类中,使其看起来像这样:

class Object
{
   public int id;
   public int size;
   public int color;
   public int author;

   // String fields for dictionary
   public string sizeString;
   public string colorString;
   public string authorString;
   //

   // Nr 1
   public Object(int id, int size, int color, int author)
   {
      this.id = id;
      this.size = size;
      this.color = color;
      this.author = author;
   }

   // Nr 2
   public Object(int id, string size, string color, string author)
   {
      this.id = id;
      this.size = sizeString;
      this.color = colorString;
      this.author = authorString;
   }

   // add, update, delete methods
}

SQL:

select o.id, s.size, c.color, a.name
from object o
join sizes s on o.size = s.id
join colors c on o.color = c.id
join authors a on o.author = a.id

如果这种方法是正确的,那么我的新构造函数 (Nr 2) 是否应该像上面那样,我的意思是我应该将 int 字段留空还是总是从 db 获取所有数据:

public Object(int id, int size, int color, int author,
              string sizeString, string colorString,
              string authorString)
   {
      this.id = id;

      this.size = size;
      this.color = color;
      this.author = author;

      this.sizeString = sizeString;
      this.colorString = colorString;
      this.authorString = authorString;
   }

SQL:

select o.id, o.size, o.color, o.author,
       s.size as sizeS, c.color as colorS, a.name as authorS
from object o
join sizes s on o.size = s.id
join colors c on o.color = c.id
join authors a on o.author = a.id

如果添加附加字符串字段的整个想法不好,请引导我朝着正确的方向前进。感谢您的帮助。

【问题讨论】:

  • 您好 user2832281,您的设计问题的正确答案很大程度上取决于您希望如何使用这些类。您只是需要将它们打印出来还是需要对它们进行完整的 CRUD(创建、读取、更新、删除)?
  • 嗨@earthling42,我只需要将它们打印出来,对于CRUD,我真的不需要它们。
  • 您可以通过调用 ToString() 将整数打印为字符串。或者,如果您只是在执行 Console.WriteLine() 之类的操作,您可以将整数传入,它会自动将其设为字符串。这不是您要找的吗?
  • 嗨@KevinCrowell,不,这不是我要找的。我需要知道的是,如果我想从字典表中获取数据,例如。颜色,因此 ID=1 的颜色在我使用连接时具有 Name=Red,我应该将此获取的颜色存储到我的 Object 类还是使用另一个包含字典数据字符串字段的类。
  • 听起来您可能希望将数据库表映射到对象类。您是否考虑过使用 ORM?如:github.com/ServiceStack/ServiceStack.OrmLite

标签: c# sql


【解决方案1】:

您可以放入将 id 解析为相应值的项目,如下所示:

using System;
using System.Collections.Generic;

namespace StackOverflow
{
    class Program
    {
        static void Main(string[] args)
        {
            IColorResolver colors = new ColorResolver();
            IObject demoObject1 = new Object(1, 1, 1, 1, colors);
            IObject demoObject2 = new Object(2, 3, 3, 3, colors);
            Console.WriteLine("demoObject1: {0}", demoObject1.Color.Name);
            Console.WriteLine("demoObject2: {0}", demoObject2.Color.Name);
            Console.ReadKey();
        }
    }

    public interface IObject
    {
        int Id { get; }
        ISize Size { get; set; }
        IColor Color { get; set; }
        IAuthor Author { get; set; }
    }

    public class Object: IObject
    {
        bool isDirty = false;

        readonly int id;
        int size;
        int color;
        int author;

        IColorResolver colors;

        public int Id { get { return this.id; } }
        public ISize Size { get; set; } //this would implement code like Color's
        public IAuthor Author { get; set; }//this would implement code like Color's
        public IColor Color
        {
            get { return colors.GetColor(color); }
            set
            {
                if (!this.color.Equals(value.Id))
                {
                    this.color = value.Id;
                    this.isDirty = true;
                }
            }
        }

        public Object(int id, int size, int color, int author, IColorResolver colorResolver)
        {
            this.id = id;
            this.size = size;
            this.color = color;
            this.author = author;

            this.colors = colorResolver;
        }

        // add, update, delete methods
    }

    public interface ILookupValue
    {
        int Id { get; }
        string Name { get; /*set;*/ } //no set since this is a lookup so we don't want to amend it
    }
    public interface IColor: ILookupValue
    {
        IColorResolver GetResolver();
    }
    public interface IAuthor : ILookupValue { /* ... */ }
    public interface ISize : ILookupValue { /* ... */ }

    public class Color : IColor
    {
        int id;
        string name;
        IColorResolver colors;
        public int Id { get { return this.id; } }
        public string Name { get { return this.name; } }
        public Color(int id, string name, IColorResolver colors)
        {
            this.id = id;
            this.name = name;
            this.colors = colors;
            this.colors.AddColor(this);
        }
        public IColorResolver GetResolver() { return this.colors; }
    }

    public interface IColorResolver
    {
        IColor GetColor(int id);
        void AddColor(IColor color);
    }

    public class ColorResolver : IColorResolver
    {
        IDictionary<int, IColor> colors = new Dictionary<int, IColor>();
        public ColorResolver()
        {
            /*
             in reality you'd probably pass a data layer object through 
             the constructor to fetch these values from your database 
            */
            new Color(1, "Red", this);
            new Color(2, "Green", this);
            new Color(3, "Blue", this);
        }
        public void AddColor(IColor color)
        {
            this.colors.Add(color.Id, color);
        }
        public IColor GetColor(int id)
        {
            IColor result;
            this.colors.TryGetValue(id, out result); //you could throw an exception here if not found
            return result;
        }
    }

}

上面代码中有大量接口的原因是这使得测试更简单;即我可以为我的任何对象创建 Mock 对象并将它们传递给我,而不是我的真实对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-08-05
    • 1970-01-01
    • 2020-02-18
    • 2021-11-06
    • 2018-03-07
    • 1970-01-01
    • 2020-07-19
    • 1970-01-01
    相关资源
    最近更新 更多