Query on object id in VQL - versant-vod

I'm currently working with the versant object database (using jvi), and have a case where I need to query the database based on an object id.
The problem is I'm running some performance tests on the database using the pole position framework, and one of the tests in that framework requires me to fetch an object from the database using either an object reference or a low level object id. Thus, I'm not allowed to reference specific fields in the employee object, but must perform the query on the object in its entirety. So, it's not allowed for me to go "select * from Employee e where e.id = 4", I need it to use the entire object.
What I'm trying to achieve is something along the lines of
Employee employee = new Employee("Mr. Pickles");
session.commit();
FundVQLQuery q = new FundVQLQuery(session,
"select * from Employee employee where employee = $1");
q.bind(employee);
q.execute();
However, this throws an EVJ_NOT_A_VALID_KEY_TYPE error. Does anyone know the correct way of doing this?

Sure you figured this out (post was months ago). What you want to do is use the GetObjectId first, to get the VOD Id of the object, then query the DB;
id = session.GetObjectId(employee);

This is how I did the whole roundtrip object → OID → object:
First you get the OID with TransSession.getOidAsLong.
TransSession session = ...;
Employee employee = new Employee("Mr. Pickles");
long oid = TransSession.getOidAsLong(employee);
session.commit();
Once you have the object ID, just grab the object from its Handle.
TransSession session = ...;
Employee employee = (Employee)session.returnHandleFromLong(oid).handleToObject();
No VQL needed.

Usually keys are integers and not strings. You are creating an Employee using just his name, perhaps the correct identifier to use is his employeeId. I need some more information on the table to know for sure.

You can try this,
FundVQLQuery vql = FundVQLQuery (session,
"select selfoid from Employee where name = $1");
vql.bind ("Mr. Pickles");
HandleEnumeration e = vql.execute ();
while ( e.hasmoreHandles() ) {
Handle handle = e.nexthandle();
}
It will return all Employees with the name "Mr. Pickles", Then loop through them.

Related

ServiceStack OrmLite - Is it possible to do a group by and have a reference to a list of the non-grouped fields?

It may be I'm still thinking in the Linq2Sql mode, but I'm having a hard time translating this to OrmLite.
I have a customers table and a loyalty card table.
I want to get a list of customers and for each customer, have a list of express cards.
My strategy is to select customers, join to loyalty cards, group by whole customer table, and then map the cards to a single property on customer as a list.
Things are not named by convention, so I don't think I can take advantage of the implicit joins.
Thanks in advance for any help.
Here is the code I have now that doesn't work:
query = query.Join<Customer, LoyaltyCard>((c, lc) => c.CustomerId == lc.CustomerId)
.GroupBy(x => x).Select((c) => new { c, Cards = ?? What goes here? });
Edit: I thought maybe this method:
var q = db.From<Customer>().Take(1);
q = q.Join<Customer, LoyaltyCard>().Select();
var customer = db.SelectMulti<Customer,LoyaltyCard>(q);
But this is giving me an ArgumentNullException on parameter "key."
It's not clear from the description or your example code what you're after, but you can fix your SelectMulti Query with:
var q = db.From<Customer>()
.Join<Customer, LoyaltyCard>();
var results = db.SelectMulti<Customer,LoyaltyCard>(q);
foreach (var tuple in results)
{
Customer customer = tuple.Item1;
LoyaltyCard custCard = tuple.Item2;
}

Retrieving Properties from DbSqlQuery

Background: Project is a Data Import utility for importing data from tsv files into a EF5 DB through DbContext.
Problem: I need to do a lookup for ForeignKeys while doing the import. I have a way to do that but the retrieval if the ID is not functioning.
So I have a TSV file example will be
Code Name MyFKTableId
codevalue namevalue select * from MyFKTable where Code = 'SE'
So when I process the file and Find a '...Id' column I know I need to do a lookup to find the FK The '...' is always the entity type so this is super simple. The problem I have is that I don't have access to the properties of the results of foundEntity
string childEntity = column.Substring(0, column.Length - 2);
DbEntityEntry recordType = myContext.Entry(childEntity.GetEntityOfReflectedType());
DbSqlQuery foundEntity = myContext.Set(recordType.Entity.GetType()).SqlQuery(dr[column])
Any suggestion would be appreciated. I need to keep this generic so we can't use known type casting. The Id Property accessible from IBaseEntity so I can cast that, but all other entity types must be not be fixed
Note: The SQL in the MyFKTableId value is not a requirement. If there is a better option allowing to get away from SqlQuery() I would be open to suggestions.
SOLVED:
Ok What I did was create a Class called IdClass that only has a Guid Property for Id. Modified my sql to only return the Id. Then implemented the SqlQuery(sql) call on the Database rather than the Set([Type]).SqlQuery(sql) like so.
IdClass x = ImportFactory.AuthoringContext.Database.SqlQuery<IdClass>(sql).FirstOrDefault();
SOLVED:
Ok What I did was create a Class called IdClass that only has a Guid Property for Id. Modified my sql to only return the Id. Then implemented the SqlQuery(sql) call on the Database rather than the Set([Type]).SqlQuery(sql) like so.
IdClass x = ImportFactory.AuthoringContext.Database.SqlQuery<IdClass>(sql).FirstOrDefault();

Using DbContext.FindBy not with a PK

Objective:
I have a table called Publication that contains Id, RecordId, EntityType and a couple other columns. I select all the records that need to be published to another database from that table. I then loop that collection to process the records and move the records to the other db.
Background:
The EntityType column is used to Identify the Set that the context needs to retrieve. I also use reflection to create a object of that type to see if it implements a certain type of interface. If the record being processed does implement that interface then I know that the RecordId for that record in the Publication table is not a PK in the Set() but rather a FK.
this code works fine when I am going after the PK values for EntityTypes that do not inherit the specific interface.
object authoringRecordVersion = PublishingFactory.AuthoringContext.Set(recordType.Entity.GetType()).Find(record.RecordId);
Problem:
DbContext.Set(EntityType).Find(PK) goes after the PrimaryKey value. How can I tell Set() to search like this sudo code example since 'Where' is not allowed
object authoringRecordVersion = PublishingFactory.AuthoringContext.Set(recordType.Entity.GetType()).Where(c => c.HeaderRecordId == record.RecordId)
Update:
I am working on Implementing the following. Will advise results tomorrow
var sql = "SELECT * from " + record.Entity + " WHERE HeaderRecordId = '" + record.RecordId + "'";
authoringRecordVersion = PublishingFactory.AuthoringContext.Set(recordType.Entity.GetType()).SqlQuery(sql).AsNoTracking();
.SqlQuery(sql).AsNoTracking();
does work effectively. Don't know why I didn't see this earlier.

NHibernate Get & string Id

I've an entity with assigned string Id on NHibernate and I've a little problem when get an entity by Id.
Example...
Suppose that have a database record like this...
Id Description
-------------------
AAA MyDescription
now, if I use "Get" method using search id "aaa"...
MYENTITYTYPE entity = Session.Get<MYENTITYTYPE>("aaa")
return right entity but Id field (entity.Id) is "aaa", while I wish it were equal to "AAA".
In summary I would like that "Get" method return the id identical to the one stored in the database...with the same case.
Is possible? How can I do?
Interesting question. My guess is that it's not possible, because the Id might exist before the DB call. Consider the following:
var foo = session.Load<Foo>("aaa"); //no DB call, foo is a proxy
Console.WriteLine(foo.Id); //Prints "aaa";
var bar = foo.Bar; //Forces loading
Console.WriteLine(foo.Id); //No matter what, the Id can't change at this point
This illustrates another reason why primary keys with meaning are usually a bad idea, especially if their input is not controlled.
Now, if instead of Get you use a query, you will get the right-cased Id:
//example with LINQ; you can use HQL, Criteria, etc
var foo = session.Query<Foo>().Single(x => x.Id == "aaa");
The drawback is that you will always go to the DB, even if the entity is already loaded.
Now, if you defined your entity as {Id, Code, Description}, where Id is a synthetic POID (I recommend Hilo or Guid) and Code is the existing string Id, you will avoid potential bugs caused by using Get instead of a query with the code.

Entity Framework 4.1 & existing database

Hi I have an existing database with a table with 30 fields, I want to split the table into many models so I could retrieve/save fields that I need and not every time retrieve/save the whole object from the db. using c#.
I think I should be using Code-First. Could someone provide an example or a tutorial link?
thanks,
You don't need to split table to be able to load a subset of field or persist subset of fields. Both operations are available with the whole table mapped to single entity as well.
For selection you simply have to use projection:
var data = from x in context.HugeEntities
select new { x.Id, x.Name };
You can use either anonymous type in projection or any non-mapped class.
For updates you can simply use:
var data = new HugeEntity { Id = existingId, Name = newName };
context.HugeEntities.Attach(data);
var dataEntry = context.Entry(data);
dataEntry.Property(d => d.Name).IsModified = true; // Only this property will be updated
context.SaveChanges();
Or:
var data = new HugeEntity { Id = existingId };
context.HugeEntities.Attach(data);
data.Name = newName;
context.SaveChanges(); // Now EF detected change of Name property and updated it
Mapping multiple entities to single table must follows very strict rules and it is possible only with table splitting were all entities must be related with one-to-one relation (and there are some problems with more than two entities per split table in code first) or with table-per-hierarchy inheritance. I don't think that you want to use any of them for this case.

Resources