Create a new record with an assigned PK - Castle ActiveRecord - nhibernate

I have a table with a GUID primary key. In ActiveRecord it is setup with a PrimaryKeyType.GuidComb. Is it possible to create this record with a manually assigned PK? If I set the primary key in the record and run Create() a new ID is assigned. If I run Save() I get an error (as one would expect).
The why:
This table is in two databases. Records need to be copied between these two databases on occasion. I would like to retain the ID as the record moves across the DBs.

No. A primary key is either generated (e.g. GuidComb) or manually assigned, it can't be both. You could create two classes that inherited from a base class defining all properties except the primary key, then each of these two classes would define their primary key as assigned or generated. But I'd recommend using SQL here, as a single INSERT INTO ... SELECT will be more efficient than using NHibernate/ActiveRecord.

I ended up setting the PrimaryKeyType to Assigned. Then I handled it with an overrided Create function:
public override void Create() {
if (ID == default(Guid)) ID = GUIDGenerator.Generate();
base.Create();
}
It would have been better to put this in OnSave, but the primary key cannot be modified in the interceptor. This works for my application, however this code will only be called if the object is explicitly created. It will not work if the object is created by cascade.

Related

Domain Driven Design Auto Incremented Entity Key

Just starting with Domain Driven Design and I've learned that you should keep your model in a valid state and when creating a new instance of a class it's recomended to put all required attributes as constructor parameters.
But, when working with auto incremented keys I just have this new ID when I call an Add method from my persistent layer. If I instanciate my objects without a key, I think they will be in a invalid state because they need some sort of unique identifier.
How should I implement my architecture in order to have my IDs before creating a new instance of my entity ?
Generated Random IDs
The pragmatic approach here is to use random IDs and generate them before instantiating an entity, e.g. in a factory. GUIDs are a common choice.
And before you ask: No, you won't run out of GUIDs :-)
Sequential IDs with ID reservation
If you must use a sequential ID for some reason, then you still have options:
Query a sequence on the DB to get the next ID. This depends on your DB product, Oracle for example has them).
Create a table with an auto-increment key that you use only as key reservation table. To get an ID, insert a row into that table - the generated key is now reserved for you, so you can use it as ID for the entity.
Note that both approaches for sequential IDs require a DB round-trip before you even start creating the entity. This is why the random IDs are usually simpler. So if you can, use random IDs.
DB-generated IDs
Another possibility is to just live with the fact that you don't have the ID at creation time, but only when the insert operation on the DB succeeds. In my experience, this makes entity creation awkward to use, so I avoid it. But for very simple cases, it may be a valid approach.
IN adition to theDmi's comments
1) You can in your factory method make sure your entity gets stored to the database. This might or might not be applicable to your domain but if you are sure that entity is going to be saved that might be a valid approach
2) You can separate the ID from the primary key from the database. I've worked with a case there something was only an order if the customer payed and at that point it would be identified by it's invoice id (a sequentual ID). that doesn't mean in the database i would need an column ID which was also the primary key of the object. You could have a primary key in the database (random guid) and till have an ID (int?) to be sequentual and null if it hasn't be filled yet.

exclusive/disjoint inheritance in SQLite

I was wondering how to implement exclusive inheritance in SQlite. By doing simply
create table Class (id integer primary key);
create table Sub1(id integer primary key references Class(id));
create table Sub2(id integer primary key references Class(id));
I have simple inheritance which does not prevent a Class to be both Sub1 and Sub2. I am looking for a way to enforce that a Class cannot be both (and optionnally, enforce it to be at least one of them).
In theory this could be possible with checks, e.g. for Sub2, something like
create table Sub2(id integer primary key references Class(id)
check(not exists(select 1 from Sub1 where Sub1.id = id limit 1)));
but this has the drawback that it would require maintenance as subclasses are added, and also that it is not accepted by SQLite (subqueries prohibited in CHECK constraints). This does not work when the check is at the table level either.
EDIT
Found a similar question (and related answers) on SO here.
You could try to use triggers (http://www.sqlite.org/lang_createtrigger.html).
For instance, you could implement your needs by creating a trigger for the table Sub(n) that, when a record is inserted in Sub(n), checks that its primary key is not alread present in Class; if it is present than fails since this means that another record with the same primary key is already present in another Sub(k) table, otherwise it insert the (primary key of the) record in Class.
In this way, you can add tables corresponding to subclasses without modifying the code of the previous tables.

Entity Framework code-first: querying a view with no primary key

Our customer has given the access to views in which there is no primary key is defined. I know Entity Framework needs a primary key for table to identify.
But for views not having primary key is it still possible to query.
I try to find but always Entity Framework gives error saying:
Error: : EntityType 'ViewWeight' has no key defined. Define the key for this EntityType.
I understand key is important for tables, but for views just to read is there any hack or way to read the values without modifying the view itself.
It's not possible in Entity Framework to have Entities without primary key.
Try to get a possible unique key from the views, combining columns, ... to create a unique primary key.
If is not possible there is a workaround, if is only a queryable view, with out need to do other operations with retrieved values such delete or update. Modify the view to add NEWID() , it will generate a unique GUID ID for each row, use this new column as primary key for your entity.
CREATE VIEW FooView AS
SELECT SELECT NEWID() AS ID,
COLUMN_A,
COLUMN_B
.....
The problem is if you repeat the same query every time you will get different ID for the same row.
Updated
If you can't not modify the view you can use Entity with a raw Sql, create the raw sql as
List<MyView> myViewItems = context.MyView.SqlQuery("SELECT NEWID() AS ID, MyView.* FROM MyView").ToList();
In your models add
public Guid ID { get; set; }
And configure the new property as the primary key.
But be careful, because there is not compilation check with this kind of code.
I create the view which includes a primary key. Ensure that all fields in the view are of a specific data type:
Number(9) rather than Number, use CAST to get the type you want
Then add a disabled primary key constraint. It won't do anything except be recognized by entity framework as a key
alter view emp_view add constraint vemp_pk primary key (empno) disable

what is local key in laravel eloquent

http://laravel.com/docs/4.2/eloquent#relationships
what does local key mean in this thing? does it mean primary key of the table? or what? for example in this code
return $this->hasOne('Phone', 'foreign_key');
return $this->hasOne('Phone', 'foreign_key', 'local_key');
local_key is the primary key of your table. You only need to specify it if your primary key is not called id AND you do not have the $primaryKey property set in your model.
I believe everything is written in the doc:
ake note that Eloquent assumes the foreign key of the relationship based on the model name. In this case, Phone model is assumed to use a user_id foreign key. If you wish to override this convention, you may pass a second argument to the hasOne method. Furthermore, you may pass a third argument to the method to specify which local column that should be used for the association:
Which basically means that 'local_key' is the name of the table column in your db which is responsible to match the related entity (phone) with your current entity (user).
If you have a look at the db, I'm sure you'll find a table user with a phone_id column, try to change it to something else (like "phone" only) and your eloquent request will crash. Then change your call to return $this->hasOne('Phone', 'user_id', 'phone'); and this might work again.

#Id for oracle.rowid

Howto declare #Entity class for oracle table w/o PK?
I has received the error message:
Column "rowid" cannot be resolved on table "LOG"
when doing mapping like this:
#Entity
public class Log implements Serializable {
...
#Id
private ROWID rowid;
...
}
Howto declare #Entity class for oracle table w/o PK?
Mapping a ROWID as Id isn't supported by standard JPA and I couldn't find any obvious proof that EclipseLink is providing an extension for this (I only found this message).
But this is not your only option and the JPA wikibook has a good paragraph about this situation:
No Primary Key
Sometimes your object or table has no
primary key. The best solution in this
case is normally to add a generated id
to the object and table. If you do not
have this option, sometimes there is a
column or set of columns in the table
that make up a unique value. You can
use this unique set of columns as your
id in JPA. The JPA Id does not
always have to match the database
table primary key constraint, nor is a
primary key or a unique constraint
required.
If your table truly has no unique
columns, then use all of the columns
as the id. Typically when this occurs
the data is read-only, so even if the
table allows duplicate rows with the
same values, the objects will be the
same anyway, so it does not matter
that JPA thinks they are the same
object. The issue with allowing
updates and deletes is that there is
no way to uniquely identify the
object's row, so all of the matching
rows will be updated or deleted.
If your object does not have an id,
but its' table does, this is fine.
Make the object and Embeddable
object, embeddable objects do not have
ids. You will need a Entity that
contains this Embeddable to persist
and query it.