如何使用 LinqToSql 将字符串值隐式转换为枚举?

发布于 2024-07-25 02:00:40 字数 486 浏览 3 评论 0原文

我问了上一个问题关于映射使用 LinqToSql 计算表上的枚举值,答案是使用 O/R 设计器将类型设置为 global::MyNamespace.TMyEnum。

如果您的枚举基于整数,那就可以了。 但是如果您的枚举基于字符串值怎么办? 最明显的应用是:

public enum TGender {
  Male,
  Female,
  Unknown,
}

数据库中的等效值是 MFU。 您无法以字符串形式键入枚举,那么如何使 LinqToSql 对象的 Gender 属性返回 TGender 值?

I asked a previous question about mapping an enumerated value on a table using LinqToSql and the answer was to use the O/R Designer to set the type to global::MyNamespace.TMyEnum.

That works OK if your enumeration is based on an integer. But what if your enum is based on a string value? The most obvious application of this is:

public enum TGender {
  Male,
  Female,
  Unknown,
}

where the equivalent values on the database are M, F and U. You can't type an enumeration as a string, so how can you make the Gender property of your LinqToSql object return a TGender value?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

七颜 2024-08-01 02:00:40

我将向 LINQ to SQL 对象添加一个 getter 属性,如下所示:

public TGender Gender
{
   switch(this.DbGender)
   {
      case "M":
        return TGender.Male;
   }
}

或者,如果您不想使用庞大的 switch 语句,则可以向枚举添加一个属性,该属性具有表示的字符串属性数据库中该值的字符串值。 然后,使用反射,获取正确的枚举,然后返回它。

下面是使用反射和属性执行此操作的示例:

public class EnumAttribute : Attribute
{
    public string DbValue
    {
        get;
        set;
    }
}

public enum TGender
{
    [EnumAttribute(DbValue = "M")]
    Male,
    [EnumAttribute(DbValue = "F")]
    Female,
    [EnumAttribute(DbValue = "U")]
    Unknown
}

    public TGender GetEnumValue(string s)
    {
        foreach (TGender item in Enum.GetValues(typeof(TGender)))
        {
            FieldInfo info = typeof(TGender).GetField(item.ToString());
            var attribs = info.GetCustomAttributes(typeof(EnumAttribute), false);
            if (attribs.Length > 0)
            {
                EnumAttribute a = attribs[0] as EnumAttribute;
                if (s == a.DbValue)
                {
                    return item;
                }
            }
        }

        throw new ArgumentException("Invalid string value.");
    }

测试一下:

var item = GetEnumValue("M");
Console.WriteLine(item);

结果为“男性”。

I'd add a getter property to my LINQ to SQL object that looks something like this:

public TGender Gender
{
   switch(this.DbGender)
   {
      case "M":
        return TGender.Male;
   }
}

Or, if you don't want to use a huge switch statement, you can add an attribute to your enum, that has a string property that represents the string value in the database for that value. Then, use reflection, get the correct enum, and return that.

Here's a sample of doing it using Reflection and Attributes:

public class EnumAttribute : Attribute
{
    public string DbValue
    {
        get;
        set;
    }
}

public enum TGender
{
    [EnumAttribute(DbValue = "M")]
    Male,
    [EnumAttribute(DbValue = "F")]
    Female,
    [EnumAttribute(DbValue = "U")]
    Unknown
}

    public TGender GetEnumValue(string s)
    {
        foreach (TGender item in Enum.GetValues(typeof(TGender)))
        {
            FieldInfo info = typeof(TGender).GetField(item.ToString());
            var attribs = info.GetCustomAttributes(typeof(EnumAttribute), false);
            if (attribs.Length > 0)
            {
                EnumAttribute a = attribs[0] as EnumAttribute;
                if (s == a.DbValue)
                {
                    return item;
                }
            }
        }

        throw new ArgumentException("Invalid string value.");
    }

To test it out:

var item = GetEnumValue("M");
Console.WriteLine(item);

This results in "Male".

假装爱人 2024-08-01 02:00:40

请允许我建议采用行为类而不是枚举的路线。 您将完全消除 switch 语句,并能够逐项关联元数据和行为。

public class Gender
{
    private static readonly Dictionary<string, Gender> _items = new Dictionary<string, Gender>();

    public static readonly Gender Male = new Gender("M", "he", age => age >= 14);
    public static readonly Gender Female = new Gender("F", "she", age => age >= 13);
    public static readonly Gender Unknown = new Gender("U", "he/she", age => null);

    public string DatabaseKey { get; private set; }
    public string Pronoun { get; private set; }
    public Func<int, bool?> CanGetMarriedInTexas { get; set; }

    private Gender(string databaseKey, string pronoun, Func<int,bool?> canGetMarriedInTexas)
    {
        DatabaseKey = databaseKey;
        Pronoun = pronoun;
        CanGetMarriedInTexas = canGetMarriedInTexas;
        _items.Add(databaseKey, this);
    }

    public static Gender GetForDatabaseKey(string databaseKey)
    {
        if (databaseKey == null)
        {
            return Unknown;
        }
        Gender gender;
        if (!_items.TryGetValue(databaseKey, out gender))
        {
            return Unknown;
        }
        return gender;
    }

    public IEnumerable<Gender> All()
    {
        return _items.Values;
    }
}

您只需询问即可,而不是使用开关来获取数据库密钥:

public void MapViewToPerson(IEditPersonInfoView view, Person person)
{
    person.Gender = view.Gender.DatabaseKey;
    // ...
}

您还可以通过简单地向 Gender 对象询问您想要的信息来应用特定于性别的行为。 例如,德克萨斯州的法定同意结婚年龄是针对特定性别的。

public void MapPersonToView(IEditPersonInfoView view, Person person)
{
    Gender gender = Gender.GetForDatabaseKey(person.Gender);
    view.Gender = gender;
    view.ShowMarriageSection = gender.CanGetMarriedInTexas(person.AgeInYears) ?? true;
    // ...
}

Allow me to suggest going the route of behavior classes instead of enums. You'll eliminate switch statements completely and have the ability to associate meta data and behaviors on an item by item basis.

public class Gender
{
    private static readonly Dictionary<string, Gender> _items = new Dictionary<string, Gender>();

    public static readonly Gender Male = new Gender("M", "he", age => age >= 14);
    public static readonly Gender Female = new Gender("F", "she", age => age >= 13);
    public static readonly Gender Unknown = new Gender("U", "he/she", age => null);

    public string DatabaseKey { get; private set; }
    public string Pronoun { get; private set; }
    public Func<int, bool?> CanGetMarriedInTexas { get; set; }

    private Gender(string databaseKey, string pronoun, Func<int,bool?> canGetMarriedInTexas)
    {
        DatabaseKey = databaseKey;
        Pronoun = pronoun;
        CanGetMarriedInTexas = canGetMarriedInTexas;
        _items.Add(databaseKey, this);
    }

    public static Gender GetForDatabaseKey(string databaseKey)
    {
        if (databaseKey == null)
        {
            return Unknown;
        }
        Gender gender;
        if (!_items.TryGetValue(databaseKey, out gender))
        {
            return Unknown;
        }
        return gender;
    }

    public IEnumerable<Gender> All()
    {
        return _items.Values;
    }
}

Instead of using a switch to get the database key you just ask for it:

public void MapViewToPerson(IEditPersonInfoView view, Person person)
{
    person.Gender = view.Gender.DatabaseKey;
    // ...
}

You can also apply gender specific behaviors by simply asking the Gender object for the information you want. For example, the legal marriage-with-consent age in Texas is gender specific.

public void MapPersonToView(IEditPersonInfoView view, Person person)
{
    Gender gender = Gender.GetForDatabaseKey(person.Gender);
    view.Gender = gender;
    view.ShowMarriageSection = gender.CanGetMarriedInTexas(person.AgeInYears) ?? true;
    // ...
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文