Skip to content
This repository has been archived by the owner on Sep 3, 2022. It is now read-only.

Forced lower casing of table names and column names in ObjectAccessor.cs #28

Open
fdsmax opened this issue Feb 27, 2014 · 6 comments
Open

Comments

@fdsmax
Copy link

fdsmax commented Feb 27, 2014

Is it mandatorily required to force the table names and column names to lower case in the ObjectAccessor.cs?

Function:- SetTableProperties :
if (IsTableSet)
Table = type.Name.ToLower(); //Is ToLower() required?

Function:- SetColumnInfo :
//If the property does not have column attribute
else
{
column.Name = member.Name.ToLower(); // Is ToLower() required?
}

Because of this, when the property class is passed through CqlContext (CqlSharp.Linq), it is not retaining the casing of the class(table/colum family) names and property names(column names) but converting to small letters. Therefore, the generated cql fails (pl note that we have the quotes " in the cql queries) and hence the table names and fields do not match with the cassandra server schema.

However, if the class is generated with CqlColumnAttribute, it works fine.

The modified ObjectAccessor.cs code is at thulya's fork: fdsmax@e41dca1

You could refer to my sample property class TLY_UserHomeStats that does not contain CqlColumnAttibute, at
https://github.com/thulya/CqlSharp.Linq/blob/master/LinqCudTestsConsole/thulyadb.cs

Thulya Team,
http://thulya.com

@reuzel
Copy link
Owner

reuzel commented Feb 27, 2014

Hi,

This is actual by design. Cassandra will by default lowercase all identifier names unless quoted. E.g create table Test (...) will result in a table named "test". This logic is repeated in CqlSharp: all identifier names are lowercased, unless a name is explicitly provided through the column and table attributes.

The quotes in the linq project are there to preserve any casing provided by the ObjectAccessor.

Regards,
Joost

On 27 feb. 2014, at 14:27, "thulya" [email protected] wrote:

Is it mandatorily required to force the table names and column names to lower case in the ObjectAccessor.cs?

Function:- SetTableProperties :
if (IsTableSet)

Table = type.Name.ToLower(); //Is ToLower() required?

Function:- SetColumnInfo :
//If the property does not have column attribute
else
{
column.Name = member.Name.ToLower(); // Is ToLower() required?
}

Because of this, when the property class is passed through CqlContext (CqlSharp.Linq), it is not retaining the casing of the class(table/colum family) names and property names(column names) but converting to small letters. Therefore, the generated cql fails (pl note that we have the quotes " in the cql queries) and hence the table names and fields do not match with the cassandra server schema.

However, if the class is generated with CqlColumnAttribute, it works fine.

The modified ObjectAccessor.cs code is at thulya's fork: thulya@e41dca1

You could refer to my sample property class TLY_UserHomeStats that does not contain CqlColumnAttibute, at
https://github.com/thulya/CqlSharp.Linq/blob/master/LinqCudTestsConsole/thulyadb.cs

Thulya Team,
http://thulya.com


Reply to this email directly or view it on GitHub.

@fdsmax
Copy link
Author

fdsmax commented Feb 27, 2014

Thanks for your reply Joost. You are right. As per the design, cassandra makes the table names and column names in lower cases and hence your CqlSharp provider works fine when used not in conjunction with LINQ provider. However, I believe, removing the forced lower casing in the ObjectAccessor.cs too should work in those scenarios as the CQL query generator or the person who writes the query should be deciding whether his table names and column names are in lower casing or sentence casing etc. If you would like to keep the default forced lower casing in CqlLinq then we may need a slightly different function to obtain the column properties from CqlSharp.Linq [to form the 'var cleanedExpression = PartialEvaluator.Evaluate(expression, CanBeEvaluatedLocally);' and at the call to 'ObjectAccessor.Instance.Columns' in your LINQ otherwise the CQL generated for the SELECT queries using your LINQ implementation fails for the cassandra tables that contain the quoted identifiers.

We had come across the practical scenario mentioned below:

Scenario 1:
Say, I have created Cassandra column family name as "TLY_UserHomeStats" and column names as "UserId", "HomeProfViewsSinceLastUpdate" etc using the doubles quotes either by using your CqlSharp (or by Cassandra Dev Studio of DataStax or our own Thulya Cassandra Management Studio that uses your CqlSharp). And then I use a LINQ or EF classes generator on the cassandra to generate C# classes. As my table names and column names contain sentence cased (or capital mixed) names, the generated property class reflects as below:

public class TLY_UserHomeStats
{

    [System.Data.Linq.Mapping.ColumnAttribute(IsPrimaryKey = true)]
    public System.String UserId { get; set; }

    public System.Int64 HomeProfViewsSinceLastUpdate { get; set; }

    public System.Int64 HomeProfViewsTotal { get; set; }

    public System.Int64 RowTimeStamp { get; set; }

}

Now, say when I execute the following query:
TLY_UserHomeStats homeStats = (from hs in thulyaDb.TLY_UserHomeStatsTable
where hs.UserId == "abcd"
select hs).SingleOrDefault();

Your ParseExpression function in the CqlContext produces a CQL that has all the identifiers in lower cases because of the call to ObjectAccessor.cs functions explained earlier. Now obviously cassandra throws 'column family not found' errors etc.

Scenario 2:
Say for example, if the LINQ or EF generate property classes from the cassandra and force those class names and property names into lower casing always (as below) then your LINQ implementation would work without eliminating the ToLowerCase in the ObjectAccessor.cs file.

public class tly_userhomestats
{

    [System.Data.Linq.Mapping.ColumnAttribute(IsPrimaryKey = true)]
    public System.String userid { get; set; }

    public System.Int64 homeprofviewssincelastupdate { get; set; }

    public System.Int64 homeprofviewstotal { get; set; }

    public System.Int64 rowtimestamp { get; set; }

}

But mostly the LINQ and EF developers prefer the casing of these objects same as in the cassandra schema. In other words, If the cassandra schema has objects in lower case then the generated classes would be in lower cases and if cassandra has them in sentence casing then these classes would be cased so. In our case, we used double quotes and produced those schema objects and hence obviously our property classes are expected to have capital letters in them and hence we either need to write an alternate method within the ObjectAccessor to obtain the Case Sensitive properties for the "Columns" or to eliminate the forced lower casing in the ObjectAccessor.cs.

Pl correct me if I didn't get anything right. Pl let me know if you would like to know more details about the above mentioned scenarios.

Thulya Team,
http://thulya.com

@reuzel
Copy link
Owner

reuzel commented Feb 28, 2014

Hi,

You have touched a topic that I have been discussing with others earlier. There are two "conflicting" naming conventions: the .Net side where typical camel casing is used for identifiers, and the Cassandra/java side where lowercase names are preferred.

To make this transition as smooth as possible, I made the decison to automatically convert the camel casing to lower casing. To override that behaviour the cqlcolumn and cqltable attributes were added. So one could create tables using cql statements without quotes (as I expect most people will do or have done earlier), and can use .Net classes with camel casing.

You take another approach, where you would like to see the class and property names in .Net follow the casing in the Cassandra table or vice versa. In many cases that would create classes that do not follow either the Cassandra or the .Net coding guidelines (like in your examples), but I can see how some developers would find this more easy to handle.

Perhaps this choice is not up to us. I tend to create an option that would allow a developer to pick one of both options. Not sure though where to put it... A setting in a connection string does not seem the correct location. Perhaps an attribute on assembly level?

Let me know what you think...

@reuzel
Copy link
Owner

reuzel commented Feb 28, 2014

As a side remark, for the DML statements I would use the ObjectAccessorl to learn about the casing of the identifiers. This way it is guaranteed to be consisted with the queries...

@reuzel
Copy link
Owner

reuzel commented Apr 27, 2014

Working on adaptations to the serialization attributes in order to support custom (user) types.

I was thinking this would be an ideal moment to fix this issue. I'm thinking along the lines of creating CqlCapitalizationAttribute that can be set on assembly, class and member level. This would set the preference of using lower cased names, or preserve the casing as present in the classes and members.

By allowing this attribute to be set on assembly level, one attribute would allow one the change the preference for all classes created within that assembly.

What do you think of this approach? Or perhaps you have gained any new insights in the mean time?

@fdsmax
Copy link
Author

fdsmax commented Jul 17, 2016

Hi Joost, hope you are doing well.. Hope your work and career is progressing well.

Regarding custom attribute for the casing, yes, using member level as well as class level CqlCapitalizationAttribute or CqlRetainCaseAttribute is a good idea. Infact, that should solve the problem as the developers can decide whether the lower casing needs to be retained for any specific field(property).

Sorry for a very long delay in replying this. Because of various aspects at my end, I could not look at CQL Sharp library for literally around 2 years since we discussed last. After several initial hurdles, finally, things are getting along positive with my business initiative and now proceeding to use Cassandra in our application. In the mean time I had chances to try out various NOSQL and NewSQL stuff, which have given me more insights into these.

Oflate the Elassandra (that combines Cassandra + Elasticsearch seem to be a promising combination for which I'm planning to use your CqlSharp for one production use case with Thulya.

I will share more details on this use case later. Will keep in touch. Have good week.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants