开发者

.NET: will Random.Random operate differently inside a static method

I am having difficulty with the following code which is inside a static method of a non-static class.

int iRand;
int rand;

rand = new Random((int)DateTime.Now.Ticks);
iRand = rand.Next(50000);

The iRand number, along with some other values, are being inserted into a new row of an Access MDB table via OLEDB. The iRand number is being inserted into a field that is part of the primary key, and the insert attempt is throwing the following exception even though the iRand number is supposed to be random:

System.Data.OleDb.OleDbException: The changes you requested to the table were not successful because they would create duplicate values in the index, primary key, or relationship.  Change the data in the field or fields that contain duplicate data, remove the index, or redefine the index to permit duplicate entries and tr开发者_JS百科y again.

Could the fact the method is static be making the iRand number stay the same, for some reason?


You should not be using Random Numbers for primary keys! First of all, yes, there is a chance of collision, in your case, n/50000,where n is the number of previously created numbers. (Thanks, Guffa) Secondly, why not use sequential values? i.e. first begin with 1, 2, 3, etc. No collision, guaranteed unique.

On the other hand, I have come across the problem of random numbers being "stuck" in a cycle, and this occurred because Random is not thread-safe. This is how I handled it : C# Random Number Generator getting stuck in a cycle

Also, why not add some logging code so that you can examine the random numbers being output, and check how much data is inside the user's DB already? (Although I am pretty sure you did that already)


No, being in a static method will make no difference. However, if you call your method repeatedly in a short space of time, you'll end up creating the same seed. That in turn means you will get the same values produced from it. By the way, the parameterless Random constructor already initializes itself from the current date/time, so your explicit use of it is redundant.

You should use a single instance of Random per thread (unfortunately Random isn't thread-safe).

You might want to read my blog post around this - as well as the comments. (At some point I'm going to rewrite it as another article, but this is what I've got at the moment.)


The reason is that you are creating Random objects that you seed with the same start value. When you create them too close in time, the DateTime.Now.Ticks value hasn't had time to change.

Create one Random object that you use for all the random numbers that you want to create in the class. You can send the object into the static method as a parameter.

Note that you will still get collisions sometimes, randomness doesn't guarantee uniqueness.


You shouldn't be using a random number as part of a composite primary key unless you are ABSOLUTELY sure that the other members of your key are enough to define the key - this error suggests that, in this case, they are not.

To be honest, I can't imagine why you would want a random in a PK, but hey - it's your show...

I always have my primary keys generated for me - even in Oracle which isn't quite as nice, I use Sequences to generate them.

And in terms of the Random number generation, see Guffa's answer.


Expanding on Jon's answer, your class should be structured like so:

static class MyClass
{

    static int iRand = new Random(); // default seed is based on ticks
    static int rand; 

    static void MyMethod()
    {
        rand= rand.Next(50000); 
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜