tags:

views:

213

answers:

8

I have a class that stores data in asp.net c# application that never changes. I really don't want to put this data in the database - I would like it to stay in the application. Here is my way to store data in the application:

public class PostVoteTypeFunctions
{
    private List<PostVoteType> postVotes = new List<PostVoteType>();
    public PostVoteTypeFunctions()
    {
        PostVoteType upvote = new PostVoteType();
        upvote.ID = 0;
        upvote.Name = "UpVote";
        upvote.PointValue = PostVotePointValue.UpVote;
        postVotes.Add(upvote);

        PostVoteType downvote = new PostVoteType();
        downvote.ID = 1;
        downvote.Name = "DownVote";
        downvote.PointValue = PostVotePointValue.DownVote;
        postVotes.Add(downvote);

        PostVoteType selectanswer = new PostVoteType();
        selectanswer.ID = 2;
        selectanswer.Name = "SelectAnswer";
        selectanswer.PointValue = PostVotePointValue.SelectAnswer;
        postVotes.Add(selectanswer);

        PostVoteType favorite = new PostVoteType();
        favorite.ID = 3;
        favorite.Name = "Favorite";
        favorite.PointValue = PostVotePointValue.Favorite;
        postVotes.Add(favorite);

        PostVoteType offensive = new PostVoteType();
        offensive.ID = 4;
        offensive.Name = "Offensive";
        offensive.PointValue = PostVotePointValue.Offensive;
        postVotes.Add(offensive);

        PostVoteType spam = new PostVoteType();
        spam.ID = 0;
        spam.Name = "Spam";
        spam.PointValue = PostVotePointValue.Spam;
        postVotes.Add(spam);
    }
}

When the constructor is called the code above is ran. I have some functions that can query the data above too. But is this the best way to store information in asp.net? if not what would you recommend?

A: 

If it doesn't change, is commonly accessed, and is the same for all users, then the .NET cache is the proper place. Have a property that yields these values. Inside, the property checks the cache for this list and returns the stored value; otherwise, it constructs it from scratch, adds to the cache, and returns the value.

This should still probably be configured in the database though, even if you cache it. I imagine that you'll need to use these value in conjunction with other data in your DB.

Patrick Karcher
+1  A: 

It is difficult to tell from the fragment of code you have posted whether you expose any of the data outside the class.

If not, then this would work. However, if not, there are several issues:

  • If you are exposing the List, you should only ever return a copy of it as an IEnumerable<PostVoteType> using the yield keyword.
  • Make sure your PostVoteType is immutable, otherwise the references can be changed and the fields used might be altered
Oded
A: 

"Never" is a very hard word indeed.

In your particular case you are asserting that not only is your PostVoteType data absolute and immutable, but so is the container collection. Frankly I don't believe you can know that, because you are not the business (your interpretation of requirement is imperfect) and you are not psychic (your knowledge of the future is imperfect).

I would suggest that you always store any data which cannot be expressed as an enumeration in some kind of repository. Where you expect relational and/or transactional and/or mutable needs that means a database, if you expect high read to write ratio that can be a config file (which I believe this case should be).

Edit: In terms of memory persistance I agree with others that the cache is the best place to store this, or rather in a domain object which is backed by cache.


Aside: your construction of PostVoteTypes is horrible - strongly suggest you want a refactor :)

annakata
oh yay, random downvotes again
annakata
What's horrible about it? What refactoring would you recommend?
David B
One of the worst non-answers I've ever seen in SO. You make assumptions as to the business requirements and then chastise the person asking the question based on your own unsubstantiated assumptions and unjustified biases. You then proceed to not give any sort of answer. And no my downvote was not random.
gmagana
@David B: At the very least they could be expressed as a proplist constructor. Better, it seems likely that ID, Name, and Value are required members and should therefore be in the constructor. Better, it seems that ID would be unique, so should not be assignable and actually generated by the data reader or just a GUID on the class, better it seems that these are just horrible fake accessors to support some kind of index or key lookup, which is just bloating an enum basically. It *was* an aside though...
annakata
@gmagana - unexplained = random, which it was. I make no assumptions of the business requirements at all, I assert that the OP should not be making inflexible choices because he (me, we, all of us) do not have perfect knowledge of things which we do not own. That's a pretty big step from "unjustified". Oh, and I said put it in a config file, so I'm not sure where non-answer comes in either. C'est la vie.
annakata
hello, would you have an example of a good implementation? I am a beginner at designing software
Luke101
A: 

create a singleton class.

nitroxn
A: 

When you need to often access the same data, and need not to store it into the underlying database, and that this data is about the same in every situation the application may encounter, then I suggest to use caching. Caching is born from these requirements. Caching is normally the fastest way to providing data as they are always kept in memory or something similar to ease and to make the access easier by the application.

Here is a nice caching tool provided with Microsoft Enterprise Library, the Caching Application Block.

I think it is worth to take the time to learn how to use it effectively.

Will Marcouiller
+1  A: 

Looking at your code, it looks like you're just trying to create a set of objects that really just put the enum PostVotePointValue into some sort of list. I.e. you already have what you need defined in just the enum itself. I would encourage you to not define the same information in two places (this data store you are asking for and the enum). This is common mistake I see people make. They create a lookup table/list, then create an enum that mirrors the rows of the table and that means they have to modify two places for any change to the list.

If PostVotePointValue isn't an enum but just some constants or if there is more info you are planning on packing in, then this isn't relevant.

Here's some examples of how to work with Enums as 'lists' from http://www.csharp-station.com/Tutorials/Lesson17.aspx

   // iterate through Volume enum by name
    public void ListEnumMembersByName()
    {
        Console.WriteLine("\n---------------------------- ");
        Console.WriteLine("Volume Enum Members by Name:");
        Console.WriteLine("----------------------------\n");

        // get a list of member names from Volume enum,
        // figure out the numeric value, and display
        foreach (string volume in Enum.GetNames(typeof(Volume)))
        {
            Console.WriteLine("Volume Member: {0}\n Value: {1}",
                volume, (byte)Enum.Parse(typeof(Volume), volume));
        }
    }

    // iterate through Volume enum by value
    public void ListEnumMembersByValue()
    {
        Console.WriteLine("\n----------------------------- ");
        Console.WriteLine("Volume Enum Members by Value:");
        Console.WriteLine("-----------------------------\n");

        // get all values (numeric values) from the Volume
        // enum type, figure out member name, and display
        foreach (byte val in Enum.GetValues(typeof(Volume)))
        {
            Console.WriteLine("Volume Value: {0}\n Member: {1}",
                val, Enum.GetName(typeof(Volume), val));
        }
    }
}

You should be able to adapt the above into an approach that will give you a list that you can use for databinding if you need it.

Jim Leonardo
+2  A: 

This is a candidate for an immutable struct that "looks like" an enumeration: (Also, I noticed you used the same id value for two of them, so I fixed that... You can use the following just as you would an enumeration...

PostVoteTypeFunctions myVar = PostVoteTypeFunctions.UpVote;

and real nice thing is that this approach requires no instance storage other than a 4-byte integer (which will be stored on stack, since it's a struct). All hard-coded values are stored in the type itself... of which only one will exist per AppDomain...

public struct PostVoteTypeFunctions 
{ 
    private int id;
    private bool isDef;
    private PostVoteTypeFunctions ( )  { } // private to prevent direct instantiation
    private PostVoteTypeFunctions(int value) { id=value; isDef = true; }

    public bool HasValue { get { return isDef; } }
    public bool isNull{ get { return !isDef; } }
    public string Name 
    { 
       get 
       {  return 
             id==1? "UpVote":
             id==2? "DownVote":
             id==3? "SelectAnswer":
             id==4? "Favorite":
             id==5? "Offensive":
             id==6? "Spam": "UnSpecified";
       }
    }
    public int PointValue 
    { 
       get 
       {  return // Why not hard code these values here as well  ?
             id==1? PostVotePointValue.UpVote:
             id==2? PostVotePointValue.DownVote
             id==3? PostVotePointValue.SelectAnswer:
             id==4? PostVotePointValue.Favorite:
             id==5? PostVotePointValue.Offensive:
             id==6? PostVotePointValue.Spam: 
                    0;
       }
    }
    // Here Add additional property values as property getters 
    // with appropriate hardcoded return values using above pattern

    // following region is the static factories that create your instances,
    //  .. in a way such that using them appears like using an enumeration
    public static PostVoteTypeFunctions UpVote = new PostVoteTypeFunctions(1);
    public static PostVoteTypeFunctions DownVote= new PostVoteTypeFunctions(2);
    public static PostVoteTypeFunctions SelectAnswer= new PostVoteTypeFunctions(3);
    public static PostVoteTypeFunctions Favorite= new PostVoteTypeFunctions(4);
    public static PostVoteTypeFunctions Offensive= new PostVoteTypeFunctions(5);
    public static PostVoteTypeFunctions Spam= new PostVoteTypeFunctions(0);       
} 
Charles Bretana
I suspect that a simple switch/case statement would, on average, provider slightly better performance and would be more readable than your use of chained ternary operators.
Cameron Peters
This can work even better if you define a nested private enumeration within the struct definition and replace the int field with it. Alternatively, define a bunch of int constants within the struct so the magic number constructors, ifs, and switch cases are more readable.
Doug McClean
@Cameron, re yr suggestion about using switches.. Don't know about performance (generally, I only address performance when there is an issue, but as to maintainability, readability, extensibility, etc., Ternerys are more concise, and are therefore MORE readable, as well as more extensible (less to modify/duplicate). This topic is addressed profusely in other posts on this forum.
Charles Bretana
@Doug, I like the idea about internal defined consts within the struct... I use that a lot for other instances where I use this pattern... but generallyu only use it for special cases... Like for example, I have a struct using this pattern that represents scheduling instruction (1st, 2nd, 3rd of the month, every Tuesday, specific calendar day of the year, etc... ) and in that struct there are constants that represent Federal Holidays (Xmas, Labor day etc.) ( ... But nested enumeration can't be private, it would have to be internal to be seen by code in the rest of the struct...)
Charles Bretana
@Charles, The last part of that isn't quite right. struct A { private enum B { Moose, Squirrel } void SomeMethod() { var c = B.Squirrel; } } compiles just fine for me (tried 2008, 2010, don't have 2005 on this computer but I think it has been this way since 1.0). Private visibility on a nested type declaration means it isn't visible outside the outer type.
Doug McClean
@Doug, yes, as you say... I just checked it out and you are exactly right... It must be I am remembering something else, although I cannot at this juncture remember exactly that might be !
Charles Bretana
A: 

I am wondering why you could not just use a simple enum for this?

public enum PostVoteType
{
    UpVote = 0,
    DownVote = 1,
    SelectAnswer = 2,
    Favorite = 3,
    Offensize = 4,
    Spam = 5
}
Mike Geise
Well if the upvote is worth 15 points - how would I put the point value in the enum. Is this possible? Please let me know. Thanks
Luke101
you could always have a static list and do something like.var type = PostVoteType.UpVote;var points = new Dictionary<PostVoteType, int>();var value = points[type];
Mike Geise