Enumeration in Repository Pattern c# - c#

How can I read from my database an int attribute that in my system is an Enumeration type attribute in the Repository Pattern, C #.
I made a class:
public class Status : Enumeration
{
public static readonly Status Active = new Status(0, "Active");
public static readonly Status Inactive = new Status(1, "Inactive");
public static readonly Status Removed = new Status(2, "Removed");
public Status()
{
}
private Status(int value, string displayName)
: base(value, displayName)
{
}
}
So in the Bank class I put a Status attribute;
At the time of reading from the bank where my Bank class is and a table with an attribute Status type int, plus the attribute gets null.

I would introduce a static method to convert integers to "enum" in your class, for example
public class Status : Enumeration
{
//YOUR CODE
public static Status FromInteger(int value){
switch(value){
case 0:
return Active;
case 1:
return Inactive;
case 2:
return Removed;
default:
throw new ArgumentException();
}
}
}
I have not dealt with DapperRepository. But quick look at ClassMapper<T> reveals that you may leverage custom conversion using AutoMap method. However, I did not find neither documentation nor example.
Therefore, I can propose only a universal solution.
public class Bank {
//Standard fields that are mapped to a table in database
public Status StatusEnum {
get {
Status.FromInteger(StatusId); //StatusId is a property mapped to table's field
}
set {
//TODO Handle null value
StatusId = value.Value;
}
}
}
NOTE:
I assume that property StatusId is a field mapped to the table's field that contains status value.
This code has obvious problem - StatusId allows values that are out of enum range. You will have to do some additional validation to maintain data consistency.

Related

Best practice for storing enums and user defined values

I am in situation where I need to store a payment type enumeration value in the database for record keeping.
The problem is that I would like to add the ability for end user define their own value types.
I understand that I can use a negative range in my enumeration for my own values since user defined types will have an id greater than 0 but would that be a correct approach?
Or maybe I should have a second column like CustomPaymentType and referenced to PaymentType table for a data consistency?
Don't use an enumeration.
Enumerations are only useful for things that are constant by their nature, like days of the week.
Instead use a reference table in the data base like CustomPaymentType (Id,PaymentTypeName)
then you can use a class that looks like:
public class CustomPaymentType
{
public string paymentTypeName { get; private set; }
public int Id { get; private set; }
// if you need "Constant payment types usable in code, just add something like:
public static CustomPaymentType CashPayment
{
get { return new CustomPaymentType() { Id = 7, paymentTypeName= "CashPayment" } }
}
public static CustomPaymentType CreditPayment
{
get { return new CustomPaymentType() { Id = 7,paymentTypeName= "CreditPayment" } }
}
}
This approach is pretty good, because you have both the ease of coding about well known specific instances that you may need while coding, and its also very extendable.

Alternative to nesting enums

I'm trying to create several enums as such, that gives the syntax of Dropdown.Category.Subcategory. However, I have been reading that this isn't such a good idea. My choice for this was mostly because I couldn't think of any other way to select different enum values depending on the choice of the category, and then the choice of the subcategory is subject to the selected enum based on the enum values.
Is there a better way to create such functionality? I would prefer to be able to easily identify both the .Category and .Subcategory names, and it would be a bonus if this code was readable.
Just to make it clear, I want to be able to choose the Category, then have an appropriate Subcategory selection.
public class Dropdown
{
public enum Gifts
{
GreetingCards,
VideoGreetings,
UnusualGifts,
ArtsAndCrafts,
HandmadeJewelry,
GiftsforGeeks,
PostcardsFrom,
RecycledCrafts,
Other
}
public enum GraphicsAndDesign
{
CartoonsAndCaricatures,
LogoDesign,
Illustration,
EbookCoversAndPackages,
WebDesignAndUI,
PhotographyAndPhotoshopping,
PresentationDesign,
FlyersAndBrochures,
BusinessCards,
BannersAndHeaders,
Architecture,
LandingPages,
Other
}
}
Create a class that cannot be inherited from externally, give it several inner classes, each extending from it. Then add static read only variables for each of the values that you want to represent:
public class Dropdown
{
private string value;
//prevent external inheritance
private Dropdown(string value)
{
this.value = value;
}
public class Gifts : Dropdown
{
//prevent external inheritance
private Gifts(string value) : base(value) { }
public static readonly Dropdown GreetingCards =
new Gifts("GreetingCards");
public static readonly Dropdown VideoGreetings =
new Gifts("VideoGreetings");
public static readonly Dropdown UnusualGifts =
new Gifts("UnusualGifts");
public static readonly Dropdown ArtsAndCrafts =
new Gifts("ArtsAndCrafts");
}
public class GraphicsAndDesign : Dropdown
{
//prevent external inheritance
private GraphicsAndDesign(string value) : base(value) { }
public static readonly Dropdown CartoonsAndCaricatures =
new GraphicsAndDesign("CartoonsAndCaricatures");
public static readonly Dropdown LogoDesign =
new GraphicsAndDesign("LogoDesign");
public static readonly Dropdown Illustration =
new GraphicsAndDesign("Illustration");
}
public override string ToString()
{
return value;
}
}
In this case every single value is actually an instance of type Dropdown, so you could have, say, a parameter to a method that accepts a Dropdown instance. With enums there is no way to say, "I want to accept any of the enums declared in the Dropdown class."
Here is some example usage:
public static void UseDropdown(Dropdown type)
{
if (type is Dropdown.Gifts)
{
if (type == Dropdown.Gifts.GreetingCards)
{
DoStuff();
}
}
else if (type is Dropdown.GraphicsAndDesign)
{
}
}
You could also have a parameter that accepts an object of type Gifts or GraphicsAndDesign, if you only want a sub-type to be valid in some context.
Sadly, using this solution there's no good way to switch on a dropdown value; you have to just use if/else if chains to check the values.
The use of an instance string value may not be required (see the first revision for a version without it) but it can be very helpful to be able to have a meaningful string value (or other kind of value; you can associate an integer, a byte, or whatever with each enumeration value).
The Equals and GetHashCode implementations should be meaningful if left without being overridden.
You can implement IComparable if the items should be logically ordered somehow, like real enums.

How to create a data-type that is a subset of possible values for another data-type

How can I create a data type that only allows particular values of another data type. For example, let's say I want to create a type that's limited to the fifty states as strings. How would I go about doing that? Using an enum and then a helper function feels a bit hacky to me.
EDIT: I suppose it is late to add this, but a compile-time error checking solution would be ideal.
For your specific example, an enum is really the best solution. For something more complex, you could use a factory method. Here's an example:
public class State
{
public string Name { get; private set; }
private State(string name)
{
this.Name = name;
}
public static State CreateState(string name)
{
// validate and throw error if invalid
return new State(name);
}
}
Use a class, and only allow specific values in the constructor. That way it's impossible to create an instance of the class that has an incorrect value. (Using an enum doesn't restrict the values to only the ones specified.)
Simple example:
public class Paint {
public string Name { get; private set; }
public Paint(string name) {
switch (name) {
case "Red":
case "Green":
case "Blue":
Name = name;
break;
default:
throw new ArgumentException("Illegal paint name '" + name + "'.");
}
}
}
Internally you can represent the value as a string or as an enum, that depends on how you want to use it.

How do you make an 'enum' that has data tied to it?

I have a Vote class and one of the properties it can have is a vote type. Such as unanimous, a 3/4 vote, a simply majority, etc. Each type needs to have a string associated with it which will describe the vote type (like "A simply majority requires 51% to pass" etc.). I need to pass these vote types/description in with my view model to my view and then I can make my drop down list with it.
Then, when the form that creates the vote is submitted I just need to bind the vote type (without description) to the Vote model (which is part of the view model).
I've only been using C# for a short time and I don't quite understand how the enums work in it. Perhaps enum is not the way to go about this.
public class VoteViewModel
{
public VoteViewModel()
{
Vote = new Vote();
}
public Vote Vote { get; set; }
public int EligibleVoters { get; set; }
}
And this is where I'll be putting the drop down.
<section class="vote-type">
<select name="">
<option value="">Select Vote Type</option>
</select>
<section class="vote-type-info">
<p class="vote-rules">To pass this vote, at least 51% of Eligible Voters must vote to approve it.</p>
</section>
</section>
Please notice I'm only showing for strings for it could be any type. In each case I mention how to extend it for more values if possible.
Using the enum as a key
You can use your enum type as a key for a dictionary (you want to be unique, so make it static and readonly in some helper class):
private static readonly Dictionary<MyEnum, string> _dict =
{
//Using dictionary initialization
{MyEnum.MyValue, "The text for MyValue"},
{MyEnum.MyOtherValue, "Some other text"},
{MyEnum.YetAnotherValue, "Something else"}
}
public static readonly Dictionary<MyEnum, string> Dict
{
get
{
return _dict;
}
}
And access the associated value:
string text = Dict[MyEnum.MyValue];
Or with:
string text;
if (Dict.TryGetValue(MyEnum.MyValue, out text))
{
//It has the value
}
else
{
//It doesn't have the value
}
This way you can access a string that is associated with the enum value. Then you can expose your Dictionary so that you can read the corresponding values.
You will need a complex type for storing more than one value. Just use your custom type isntead of string. Or if available you can use Tuples.
Accesing the Dictionary may mean an extra annoyance and hopefully it will not mean a threading problem too.
Enum.GetName
You can use Enum.GetName to read the name of the values of your enum:
string text = Enum.GetName(MyEnum.MyValue);
//text will have the text "MyValue"
//or
var some = MyEnum.MyValue;
string text = Enum.GetName(some);
Note: ToString() should work too.
Sadly, this will not work for something else than the string.
Also it has the drawback that you cannot put any text there (it has to be a valid identifier).
Custom Attributes
You will have to declare an attribute type:
[AttributeUsage(AttributeTargets.Field)]
public class EnumValueAttribute : System.Attribute
{
public readonly string _value;
public string Value
{
get
{
return _value;
}
}
public EnumValueAttribute(string value) // value is a positional parameter
{
//beware: value can be null...
// ...but we don't want to throw exceptions here
_value = value;
}
}
Now you apply the attribute to your enum:
public enum MyEnum
{
[EnumValue("The text for MyValue")]
MyValue = 1,
[EnumValue("Some other text")]
MyOtherValue = 2,
[EnumValue("Something else")]
YetAnotherValue = 3
}
Lastly you will need to read the attribute back:
public static string GetValue(MyEnum enumValue)
{
FieldInfo fieldInfo = typeof(MyEnum).GetField(enumValue.ToString());
if (!ReferenceEquals(fieldInfo, null))
{
object[] attributes = fieldInfo.GetCustomAttributes(typeof(EnumValueAttribute), true);
if (!ReferenceEquals(attributes, null) && attributes.Length > 0)
{
return ((EnumValueAttribute)attributes[0]).Value;
}
}
//Not valid value or it didn't have the attribute
return null;
}
Now you can call it:
string text1 = GetValue(MyEnum.MyValue);
//text1 will have the text "MyValue"
//or
var some = MyEnum.MyValue;
string text2 = GetValue(some);
You can add more fields to your attribute class and use them to pass any other value you may need.
But this requires reflexion, and it may not be available if you are running in a sandbox. Also it will retrieve the attributes each time, creating some short lived objects in the proccess.
Emulate Enum
You can emulate an enum with a sealed class that has no public constructor and exposes static readonly instances of itself:
public sealed class MyEnumEmu
{
private static readonly string myValue = new MyEnumEmu("The text for MyValue");
private static readonly string myOtherValue = new MyEnumEmu("Some other text");
private static readonly string yetAnotherValue = new MyEnumEmu("Something else");
public static MyEnumEmu MyValue
{
get
{
return myValue;
}
}
public static MyEnumEmu MyOtherValue
{
get
{
return myOtherValue;
}
}
public static MyEnumEmu YetAnotherValue
{
get
{
return yetAnotherValue;
}
}
private string _value;
private MyEnumEmu(string value)
{
//Really, we are in control of the callers of this constructor...
//... but, just for good measure:
if (value == null)
{
throw new ArgumentNullException("value");
}
else
{
_value = value;
}
}
public string Value
{
get
{
return _value;
}
}
}
Use it as always:
var some = MyEnumEmu.MyValue;
And access the associated value:
string text = MyEnumEmu.MyValue.Value;
//text will have the text "MyValue"
//or
string text = some.Value;
This is the more flexible of all, you can either use a complex type instead of string or add extra fields for passing more than a single value.
But... it is not really an enum.
You could create a "constant" dictionary (or rather readonly static, since you can't create a constant dictionary) around your Enum.
public enum VoteType { Unanimous = 1, SimpleMajority = 2, ... }
public static readonly Dictionary<VoteType, string> VoteDescriptions = new Dictionary<VoteType, string>
{
{ VoteType.Unanimous, "Unanimous description" },
{ VoteType.SimpleMajority, "Simple majority" },
...
};
public class Vote()
{
public VoteType VoteSelectType { get; set; }
}
public enum VoteType
{
[Display(Name = "Enter Text Here")]
unanimous = 1,
[Display(Name = "Enter Text Here")]
threequatervote = 2,
[Display(Name = "Enter Text Here")]
simplymajority = 3
}
Goto here this is pretty much your solution
How do I populate a dropdownlist with enum values?
You can use enums if you want but you need to decide how to make the link between the enum value and what you want to display. For example, an enum value of SimpleMajority you would want displayed as "Simple Majority". One way to do this is using the Description attribute and a helper class as described here.
However, you might find it easier to set up a lightweight collection class to store vote type values and their description. This could be as simple as a Dictionary<int, string> You will probably find this a more straightforward approach.
Since you have the type and description I'll better suggest you to create a class that wraps up both instead of enum. The advantage is you can reduce more work and it's very flexible.
public class VoteType
{
public string Name{ get; set; }
public string Description{ get; set; }
}
Now your Vote class will have reference to this VoteType.
public class Vote
{
...
public VoteType Type{ get; set; }
}
In your VoteViewModel you better have a class that contains all the VoteTypes.
public class VoteViewModel
{
...
public IEnumerable<SelectListItem> VoteTypes{ get; set; }
}
Now you can easily bind the VoteTypes in a dropdownlist.
#model VoteViewModel
#Html.DropDiwnListFor(m => m.VoteTypes,...)
I have used this before, it is really handy.
http://www.codeproject.com/Articles/13821/Adding-Descriptions-to-your-Enumerations
In short what it lets you do is:
public enum MyColors{
[Description("The Color of my skin")]
White,
[Description("Bulls like this color")]
Red,
[Description("The color of slime")]
Green
}
and then get the description back by simply calling:
String desc = GetDescription(MyColor.Green);
It does use reflection though, so there is a tradeoff between simplicity and a slight performance hit. Most of the time I'd take the performance hit...

How can I implement a table?

Suppose you need to store some values ​​in a table formed by several columns (such as a relational database): for example, int for the first column, string for the second one, DateTime for the third one, etc..
If one or more column are like a primary key, then we could use an IDictionary, whose Key would be the set of fields that acts as a primary key. The remaining fields represent the Value. In this case I could create one or two classes/structures. For example, if the primary key is simply an existing type, we will only have to create a class/struct like the following:
public class MyValue
{
public int Field1;
public double Field2;
public string Field3;
}
The dictionary could be a Dictionary<int, MyValue>, while the table could be the following.
public class MyTable
{
private Dictionary<int, MyValue> _table;
...
}
Obviously, according to the application domain there may be ranges and/or rules of validity for the above fields: for example, Field1 may have to be positive, and so on...
As a first alternative I could design the MyValue class so that it throws some exceptions in order to identify the "violation of rules". But perhaps this approach might be excessive, especially if the class MyValue is used only internally to MyTable: in this case I would write code like the following and handle validity error within MyTable class: that is, MyTable class checks the data fields before inserting them into the dictionary, so MyValue would be a "stupid" class...
namespace MyNamespace
{
class MyValue
{
// only public fields
}
public class MyTable
{
private Dictionary<int, MyValue> _table;
...
public void Add(int key, int field1, double field2, string field3)
{
// some code to check validity range for fields
...
}
}
}
Is this solution correct? Or should I avoid this approach? Should I always define a class/struct in a complete manner (exceptions handling, Equals, GetHashCode methods?
What you've done looks overly complicated, brittle and will ultimately lead to maintainability nightmares.
I'd say you have two options.
Option one: use a DataTable. It doesn't have to be backed by an actual database and you can define it's layout (including column definitions) at runtime.
Option two: Define a class that implements your "record" logic. Define a Collection to hold that class. Use LINQ to "query" the collection for whatever you need.
The primary difference between the two options is that a DataTable is very limited in the type of rules you can employ. Option 2, OTOH, allows you to build precisely what you want.
I would let the values check their consistency themselves. If you implement the fields as properties, the setter can do checks and throw an exception is the value is out of range for instance.
I also would suggest a somewhat more flexible approach. Define an interface that your table records must implement
public interface IRecord<PK>
{
PK ID { get; }
}
Records must have an ID, which will be used as primary key. We use a generic primary key type PK.
Now you can define a value class like this
public class MyValue : IRecord<int>
{
private int _field1;
public int Field1
{
get { return _field1; }
set
{
if (value < 0 || value > 1000) {
throw new ArgumentException("Value of 'Field1' must be between 0 and 1000");
}
_field1 = value;
}
}
public double Field2;
#region IRecord<int> Members
public int ID { get { return Field1; } }
#endregion
}
As you can see, it implements IRecord<int> and returns Field1 as ID. Field1 checks the values passed to it. If the primary key is made up of several fields you can use a type like Tuple (.NET 4.0) as primary key type. Like IRecord<Tuple<int,double>>.
Now you can define a generic table
public class Table<T, PK>
where T : IRecord<PK>
{
private Dictionary<PK, T> _table = new Dictionary<PK, T>();
public void Add(T item)
{
_table.Add(item.ID, item);
}
}
You can define specific tables like this
public class MyTable : Table<MyValue, int>
{
}
UPDATE:
Alternatively, you could let records implement an explicit error handling
public interface IRecord<PK> {
PK ID { get; }
bool IsValid { get; }
string[] Errors { get; }
}

Categories

Resources