Castle ActiveRecord Seeding Primary Key Value - activerecord

I am wondering how to 'seed' an auto incrementing primary key value using Castle AR? For Example wanting the Orders table primary keys to start out as 10000. Is this something that is 1. possible 2. a good solution for creating order numbers?
Maybe there is a way to have consecutive auto incrementing field on the DB that is NOT the pk, seeded to 10000?

Castle ActiveRecord is built on top of NHibernate and features of AR heavily rely on features of NHibernate. NHibernate contains several primary key generators:
1. native - This is the default generator. If you specify this then NHibernate automatically chooses generator type based on underlying database. For example, if I would have used native instead of identity in the above mapping snippet you will still get the same SQL because NHibernate is smart enough to understand that the underlying database SQL Server and it supports identity columns. NHibernate converts the returned values using Convert.ChangeType method.
2. identity - This can be used with Identity columns provided with SQL Server, MySQL, Sybase etc.,
3. sequence - Firebird, DB2, PostgreSQL, Oracle, SAP DB supports sequences
4. increment - This generator does not uses any database feature like sequence or identity. NHibernate automatically increments 1 to last primary key value. This generator is helpful when dealing with single database system but it does not help in cluster based environment.
5. hilo - Hi/Lo algorithm is used to generate primary key values. This is very efficient when compared to other generator types. When used, NHibernate creates a separate table named hibernate_unique_key and creates a column named next_hi and then NHibernate uses this table as a reference when INSERT happens. We will talk elaborately on this later in this post.
6. uuid.hex - Uses System.Guid and its ToString method for generating string based primary key values.
7. guid - This can be used when the class property type is Guid.
8. guid.comb - This is similar as guid but uses a different algorithm to produce primary key values. Note that uuid.hex, guid, guid.comb uses UNIQUEIDENTIFIER as a column data type in SQL Server.
9. assigned - last but not least, this generator assumes that the primary key value is assigned by the user.
So you can see that there are no such build-in functionality. In order to create an order number you can use 2 ways:
1. select max order and manually set it
2. add some insert trigger to database
In my opinion you should use first way because in this way you will not rely on database. And you can reuse this functionality when you will need to move an object up or down. I'm usually using this way.

Related

Supporting ABP's IEntityCache for entities with multi-column primary keys

The current implementation of IEntityCache supports a 1-column primary key type (default int, can be sent as a different type, e.g. long, string).
Currently there are 2 approaches (that I can see) to enable caching for tables/entities whose primary key consists of 2 (or more) columns, such as 2 string columns:
Modify the schema of the table and simply add an integer Id column (auto-increment) whose sole purpose is to enable the IEntityCache to do its magic. The application logic querying the entity would remain untouched as it would still use the 2-column unique index. Modifying the schema however may not be an option, and another problem is that the upper application layers (Domain, AppServices) are not aware of the Id they need to query, instead they are aware of the entity's 2 keys.
Rewrite a new implementation of IEntityCache to support multiple columns (e.g. IEntityCache<string, string>?). Not sure if this is even feasible given the cachemanager's limitations?
Here's the question: Would the inner workings of the ICacheManager - itself being an abstraction over different cache providers (e.g. IMemoryCache, Redis etc...) - prevent a multi-column implementation?

How to use ActiveRecord (without Rails) with database that doesn't have primary keys

I now writing automation program for system based on MSSQL Server, using Ruby 1.9.3 and ActiveRecord 3.1.6 without Rails.
Tables have nonstandard ids (stk_id, urb_id, instead of id), also some tables haven't primary keys.
Before I added column id and set it as primary key my program worked very slowly. I waited nearly 3 minutes while the program makes two operations of selection and some little processing in table with 9000 records. But when I added column id and set it as primary key, these operations were finished in less then 10 secs.
Yet another problem I found in deletion operation: it doesn't work at all without primary key in table. Error when trying to delete without primary key:
undefined method `to_sym' for nil:NilClass
I can't modify the table structure of the production database. Maybe someone knows how to solve this problem without adding id columns and setting primary keys?
Remark: A database without primary keys is BAD !
http://www.helium.com/items/1539899-why-a-relational-database-needs-a-primary-key
Using nonstandard keys is no problem, just use self.primary_key = "stk_id"
You may also use composite_primary_keys:
https://github.com/drnic/composite_primary_keys
Create indexed views on each of the tables with no primary key. A unique clustered index as well as other indexes as needed can be applied. Including a single table in the view should prevent you from violating the many conditions an indexed view requires/prohibits.
I suggest looking into using Sequel instead of ActiveRecord. It is not opinionated about the database schema like ActiveRecord is and may be easier to use with a database schema you can't modify.

SQL Azure and Membership Provider Tenant ID

What might be a good way to introduce BIGINT into the ASP.NET Membership functionality to reference users uniquely and to use that BIGINT field as a tenant_id? It would be perfect to keep the existing functionality generating UserIds in the form of GUIDs and not to implement a membership provider from ground zero. Since application will be running on multiple servers, the BIGINT tenant_id must be unique and it should not depend on some central authority generating these IDs. It will be easy to use these tenant_id with a SPLIT AT command down the road which will allow bucketing users into new federated members. Any thoughts on this?
Thanks
You can use bigint. But you may have to modify all stored procedures that rely on user ID. Making ID global unique is usually not a problem. As long as the ID is the primary key, database will force it to be unique. Otherwise you will get errors when inserting new data (in that case, you can modify ID and retry).
So the most important difference is you may need to modify stored procedures. You have a choice here. If you use GUID, you don't need to do anything. But it may be difficult to predict how to split the federation to balance queries. As pointed out in another thread (http://stackoverflow.com/questions/10885768/sql-azure-split-on-uniqueidentifier-guid/10890552#comment14211028_10890552), you can sort existing data at the mid point. But you don't know future data will be inserted in which federation. There's a potential risk that federations will become unbalanced, and you may need to merge and split them at a regular interval to keep them in shape.
By using bigint, you have better control over the key. For example, you have two federations. The first has ID from 1 to 10000, and the second has ID from 10001 to 20000. When creating a new user, you first check how many records are in each federation. Suppose federation 1 has 500 records and federation 2 has 1000 records, to balance the load, you choose to insert to federation 1, so you choose an ID between 1 and 10000. But using bigint, you may need to do more work to modify stored procedures.

entity framework returning only one value but the list size is correct

Entity framework returning only one value but the list size is correct
I have a table that does not have primary id and I need to get or select all the values in it.
What I see is when I do the selection with linq the number of objects is correct but it is the first row over and over.
I am simply doing something like this
List<MyValueType> valuesInDB = myDb.MyValueTypes.ToList();
Problem is I may get thousands of rows (which is correct) but the rows all have the same exact data.
I am using VS 2010 and used the wizard to create my EF object.
The problem is that entity framework is not able to work with entity without a key. So if your table doesn't specify a key, entity framework will infer its own. The key created by EF is composed of all non-nullable non-binary columns.
So if you for example have single non-nullable column in your entity which have only very small set of values (like enum) you will be able to load only single entity "per value". The reason is an inner implementation of the context and the state manager which uses Identity map pattern. When data record is retrieved from database, EF will first check an entity key and tries to find an object with the same key in its internal storage. If an object is found it will use that object instead of data record retrieved (despite of different data). If an object with the key is not found a new object is materialized and added to internal storage.
That is the purpose of Identity map - object with given key should be created only once by each context. Identity map is core pattern in ORM.
I wrote about Identity map also in this question.
I would suggest searching for the word "Warning" in your EDM's designer.cs file. It might tell you if Entity Framework is having any issues with your table.
I really can't comment much in the absence of the table design. I tried replicating your problem but wasn't able to do so. Here is what I did:
Created a table with no primary key but it had a unique key on an ID column. Entity Framework was able to infer a primary key and when I fetched the data, I not only got the correct number of rows but also the corrects data in those rows.
Created a table with no primary key and no unique key. Also there was no column called ID. Entity Framework excluded this table in the EDM that was generated. Consequently I wasn't able to query this table at all.This was displayed as a warning in the EDM designer file.
It would be better if you can share the create script for your table.

Random ID generation on Sign Up - Database Performance

I am making a site that each account will have an ID.
But, I didn't want to make it incrementable, meaning:
id=1
id=2
...
id=1000
What I want is to have random IDs:
id=2355
id=5647734
id=23532
...
(The reason is to avoid robots to check all accounts profiles by just incrementing a ID in URL - and maybe other reason, but that is not the question)
But, I am worried about performance on registration.
It will be something like this:
while (RANDOM_ID is not taken): generate new RANDOM_ID
On generating a new ID for the new account, I will query database (MySQL) to check if the ID exists, for each generation.
Is there any better solution for this?
Is there any disadvantage of using random IDs?
Thanks in advance.
There are many, many reasons not to do this:
Your solution, as written, is not transactionally-safe; two transactions at the same time could both generate the same "random" ID.
If you serialize the transaction in order to make it safe, you will slaughter performance because the query will keep every single collision row locked until it finds a spare ID.
Using a random ID as the primary key will fragment the hell out of your clustered index. This is bad enough with uuids - the whole point of an auto-generated identity column is so you can generate a safe sequence out of it.
Why not use a regular primary key, but just don't use that in any of your URLs? Generate a secondary non-sequential ID along with it - such as a uuid - index it, and use this column in any public-facing segments of your application instead of the primary key if you are really worried about security.
You can use UUIDs. It's a unique identifier generated based partly on timestamp. It's almost certainly guaranteed to be unique so you don't have to do a query to check.
i do not know what language you're using, but there should be library or sample code for this for most languages.
Yes you can use UUID but keep your auto_increment field. Just add a new field and set it so something like: md5(microtime(true).rand()) or whatever other method you like and use that unike key along the site to make the links instead to expose the primary key in urls.

Resources