Get OrmLite database column name from property name - servicestack

Let's say I have this class:
public class FooBar
{
public long Id {get; set;}
public string BarFoo {get; set;}
}
OrmLite when using postgresql will create table name foo_bar and columns id, and bar_foo.
I can get the table name for use in a custom query like so:
db.ExecuteSql($"INSERT INTO {db.GetTableName<SomeOtherClass>()}(bar_foo) SELECT bar_foo FROM {db.GetTableName<FooBar>()}");
If the naming convention changes or the property is re-named then the query breaks because the column bar_foo is defined as a string.
How do I define the column names in the same fashion I am defining the table names?

You can get the table & column names from the dialect provider, e.g:
var dialect = db.Dialect(); //older API db.GetDialectProvider()
By their name where it will use the configured NamingStrategy:
var tableName = dialect.GetQuotedTableName(nameof(FooBar));
var columnName = dialect.GetQuotedColumnName(nameof(FooBar.BarFoo));
By OrmLite's model & field definition where it will also make use of any RDBMS [Alias] customizations defined on the model:
var modelDef = typeof(FooBar).GetModelMetadata();
var fieldDef = modelDef.GetFieldDefinition(nameof(FooBar.BarFoo));
var tableName = dialect.GetQuotedTableName(modelDef);
var columnName = dialect.GetQuotedColumnName(modelDef,fieldDef);

Related

creating uuid type field in Cassandra table using CassandraAdminOperations.createTable

I have problem when create table with UUID type field using CassandraAdminOperations.createTable. I defined field in table with type uuid, but when the table was created using CassandraAdminOperations.createTable, the field was created as timeuuid. Is there any way to force the field to uuid instead of timeuuid ?
Here is the field definition in class,
#PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private UUID id;
#Column(value = "url")
private String url;
But when call CassandraAdminOperations.createTable to create the table, the log shows the following and the id filed was created as timeuuid,
00:43:23.877 [localhost-startStop-1] DEBUG o.s.d.c.core.CassandraAdminTemplate - CREATE TABLE IF NOT EXISTS id_to_url_map (id timeuuid, url text, PRIMARY KEY (id));
Thanks!
I had the same problem. But after some investigation, I found that you can add #CassandraType annotation, and explicitly specify the class.
import com.datastax.driver.core.DataType;
#PrimaryKeyColumn(name = "id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
#CassandraType(type = DataType.Name.UUID)
private UUID id;

need a counter query which give all counter for a primary key using hector API

I am using hector API for cassandra.
i create a counter table like follows
private void addColumnFamilyCounter(ThriftCluster cluster, String cfName, int rowCacheKeysToSave) {
String cassandraKeyspace = this.env.getProperty("cassandra.keyspace");
ThriftCfDef cfd =
new ThriftCfDef(cassandraKeyspace, cfName, ComparatorType.UTF8TYPE);
cfd.setRowCacheKeysToSave(rowCacheKeysToSave);
cfd.setDefaultValidationClass(ComparatorType.COUNTERTYPE.getClassName());
cluster.addColumnFamily(cfd);
}
and call the above method like follows
addColumnFamilyCounter(cluster, COUNTER_CF, 0);
The format of the table is like follows
Primary key columns
Munich jingle : 1
mingle : 2
tingle : 1
pingle : 5
Now i want to execute a query to get all the columns and their values under Munich. is there any way i can get all the columns.
What i knw till now is the following query but it gives me value for only a combination of primary key and a column key.
#Override
public long getTagCounter(String domain, String tag) {
CounterQuery<String, String> counter =
new ThriftCounterColumnQuery<String, String>(keyspaceOperator,
StringSerializer.get(),
StringSerializer.get());
counter.setColumnFamily(TAG_COUNTER_CF).setKey("p_key").setName("name");
return counter.execute().get().getValue();
}
okay i found answer by myself.I hope it will be helpful to other
CounterSlice<String> query = HFactory.createCounterSliceQuery(keyspaceOperator , StringSerializer.get(), StringSerializer.get())
.setColumnFamily("CF")
.setKey("PK")
.setRange(null, null, false, Integer.MAX_VALUE).execute().get();
for(HCounterColumn<String> col : query.getColumns()){
log.info(col.getName());
log.info(col.getvalue());
}

Astyanax getKey with compound key

I would like to run the following code with a compound primary key.
Column<String> result = keyspace.prepareQuery(CF_COUNTER1)
.getKey(rowKey)
.getColumn("Column1")
.execute().getResult();
Long counterValue = result.getLongValue();
Research seems to show that it can be a string that represents a key (if it's not a compound primary key). The documentation says that it is of type K, alas, I am not very experience with Java, and have no idea what that means. Is it just a base type that lots of stuff inherits from? If so, I'm not really any closer to knowing what getKey(K) needs in order to handle a compound key (am I?).
You just need to write a class that fits the columns in your data model. You can then give this class to Astyanax in your mutations or queries.
For example, if you had a data model like this
CREATE TABLE fishblogs (
userid varchar,
when timestamp,
fishtype varchar,
blog varchar,
image blob,
PRIMARY KEY (userid, when, fishtype)
);
you would create a class like this:
public class FishBlog {
#Component(ordinal = 0)
public long when;
#Component(ordinal = 1)
public String fishtype;
#Component(ordinal = 2)
public String field;
public FishBlog() {
}
}
When and fishtype form your composite column key and are represented by the FishBlog class. Userid would be your row/partition key and can be of the simple "string" type.
Have a look at this blog explaining in great detail how to insert data with composite keys (where I took this example from).
Hope that helps.

Querying multiple tables with a where clause in LINQ to SQL

Forgive my ignorance with Linq to SQL but...
How do you query mulitple tables in one fell swoop?
Example:
I want to query, say 4 tables for a title that includes the following word "penguin". Funnily enough each table also has a field called TITLE.
Tables are like so:
I want to query each table (column: TITLE) for the word "penguin". Each table is referenced (via foreign key) to a parent table that is simply called Reference, and is linked on a column called REF_ID. So ideally the result should come back with a list of REF_ID's where the query criteria was matched.
If you can help you will be richly rewarded....... (with a green tick ;)
The code I have works for just one table - but not for two:
var refs = db.REFERENCEs
.Include(r => r.BOOK).Where(r => r.BOOK.TITLE.Contains(titleString)).Include(r => r.JOURNAL.AUTHORs)
.Include(r => r.JOURNAL).Where(r => r.JOURNAL.TITLE.Contains(titleString));
I had a similar scenario a while back and ended up creating a view that unioned my tables and then mapped that view to a LINQ-to-SQL entity.
Something like this:
create view dbo.References as
select ref_id, title, 'Book' as source from dbo.Book
union all
select ref_id, title, 'Journal' from dbo.Journal
union all
select ref_id, title, 'Magazine' from dbo.Magazine
union all
select ref_id, title, 'Report' from dbo.Report
The mapping would look like this (using attributes):
[Table(Name="References")]
public class Reference {
[Column(Name="Ref_Id", IsPrimaryKey=true)]
public int Id {get;set;}
[Column]
public string Title {get;set;}
[Column]
public string Source {get;set;}
}
Then a query might look like this:
var query = db.GetTable<Reference>().Where(r => r.Title.Contains(titleString));

Subsonic 3 Sql Join using SimpleRepository can't join on columns with same name?

I'm trying to using the Subsonic Fluent query interface to create a simple inner join between two tables:
[SearchJobResults]
PK SearchJobResultId int
Name string
Desc string
[ParseResults]
PK ParseResultId int
Name string
SearchJobResultId int
There is a 1 to 1 relationship between these tables.
Keep in mind, I'm not using ActiveRecord. I have classes for ParseResult and SearchJobResult that work fine.
IDataProvider p = ProviderFactory.GetProvider("DemacDB");
SqlQuery query = new SqlQuery(p);
var q = new Select(p).From("ParseResults")
.InnerJoin<SearchJobResult>("SearchJobResultId","SearchJobResultId").GetRecordCount();
This code throws an exception:
Test method Models.SearchTests.TestSubsonicQueryMethods threw exception: System.InvalidOperationException: Don't know which column to join to - can't find column SearchJobResultId in table ParseResults.
I've looked at the source code for SubSonic to see where this execption is coming from:
private void CreateJoin<T>(string fromColumnName, string toColumnName, Join.JoinType type)
{
//see if we can find the table
var toTable = _provider.FindOrCreateTable(typeof(T));
//the assumption here is that the FromTable[0] is the table to join from
if(FromTables.Count == 0)
throw new InvalidOperationException("Can't join if there's no table to join to - make sure to use From() before InnerJoin");
if(toTable == null)
throw new InvalidOperationException("Can't find the table for this type. Try using the Column instead");
var fromColumn = FromTables[0].GetColumn(fromColumnName);
if(fromColumn == null)
throw new InvalidOperationException("Don't know which column to join to - can't find column " + fromColumnName + " in table " + FromTables[0].Name);
var toColumn = toTable.GetColumn(toColumnName);
if(toColumn == null)
throw new InvalidOperationException("Don't know which column to join to - can't find column " + toColumnName + " in table " + toTable.Name);
CreateJoin(fromColumn, toColumn, Join.JoinType.Inner);
}
I've tried using Aliases but that fails. Additionally, if I just do a simple query like this it works fine:
var d = new Select(p).From("ParseResults").GetRecordCount();
Turns out you need to use the Typed T overloads of From/Join to get this working.
var b = new Select(p).From<ParseResult>().InnerJoin<SearchJobResult>("SearchJobResultId", "SearchJobResultId").GetRecordCount();
Works as the FromTables collection in Subsonic now correctly gets enumerated because it's reading the type from the actual object and not the DB.

Resources