C# conventions / best practices - c#

I was wondering is constantly reusing namespace names is valid for c# conventions/best practises.
I am develop most of my programs in Java, and i would have a packet for implementations, eg:
com.ajravindiran.jolt.game.items.sql
com.ajravindiran.jolt.game.users.sql
com.ajravindiran.jolt.events.impl
com.ajravindiran.jolt.tasks.impl
Let's talk about com.ajravindiran.jolt.game.items.sql, which is most close my situation. I current wrote a library that wraps the MySQL Connection/Net into a OODBMS.
So i have an interface called ISqlDataObject which has the following members:
bool Insert(SqlDatabaseClient client);
bool Delete(SqlDatabaseClient client);
bool Update(SqlDatabaseClient client);
bool Load(SqlDatabaseClient client);
and used like such:
public class SqlItem : Item, ISqlDataObject
{
public bool Load(SqlDatabaseClient client)
{
client.AddParameter("id", this.Id);
DataRow row = client.ReadDataRow("SELECT * FROM character_items WHERE item_uid = #id;");
this.Examine = (string)row["examine_quote"];
...
}
...
}
called:
SqlItem item = new SqlItem(int itemid);
GameEngine.Database.Load(item);
Console.WriteLine(item.Examine);
So i was wondering if it's ok to add the sql editions of the items into something like JoltEnvironment.Game.Items.Sql or should i just keep it at JoltEnvironment.Game.Items?
Thanks in adnvanced, AJ Ravindiran.

For naming conventions and rules, see MSDN's Framework Guidelines on Names of Namespaces.
That being said, that won't cover this specific issue:
So i was wondering if it's ok to add the sql editions of the items into something like JoltEnvironment.Game.Items.Sql or should i just keep it at JoltEnvironment.Game.Items?
It is okay to do either, and the most appropriate one depends a bit on your specific needs.
If the game items will be used pervasively throughout the game, but the data access will only be used by a small portion, I would probably split it out into its own namespace (though probably not called Sql - I'd probably use Data or DataAccess, since you may eventually want to add non-SQL related information there, too).
If, however, you'll always use these classes along with the classes in the Items namespace, I'd probably leave them in a single namespace.

You're asking about naming conventions, and the answer is, it's really up to you.
I allow for extra levels of hierarchy in a namespace if there will be multiple implementations. In your case, the .Sql is appropriate if there is some other storage mechanism that doesn't use Sql for queries. Maybe it's XML/Xpath. But if you don't have that, then it seems like the .Sql layer of naming isn't necessary.
At that poiint, though, I'm wondering why you would use {games,users} at the prior level. Feels like the namespace is more naturally
JoltEnvironment.Game.Storage
..And the Fully-qualified type names would be
JoltEnvironment.Game.Storage.SqlItem
JoltEnvironment.Game.Storage.SqlUser
and so on.
If a namespace, like JoltEnvironment.Game.Items, has only one or two classes, it seems like it ought to be collapsed into a higher level namespace.

What are you calling SQL Editions? Versions of SQL Server? Or Version of Database Connections? If the later, I would do something like:
JoltEnvironment.Game.Items.DataAccess.SQLServer
JoltEnvironment.Game.Items.DataAccess.MySQL
JoltEnvironment.Game.Items.DataAccess.Oracle
etc...
If the former, I thought that ADO.NET would take care of that for you anyway, based on the provider, so everything under the same namespace would be ok.

Related

How to log/get a SQL query auto-generated by Dapper Extensions?

I am using Dapper Extensions (DE) as ORM. It is consumed in Data Access Layer which is implemented using Repository pattern. SQL Express is back-end RDBMS.
DE automatically generates most of the queries for me. I want to log those auto-generated queries for debugging purpose.
There are two ways I can see to achieve this: -
Get the SQL query generated by DE (before or after it is executed) and write it to log. This is preferred way for me as I already have my logging module (using log4net) in place. The only thing I need is the SQL generated by DE.
Integrate DE with some logging tool. I read this answer. It looks possible using MiniProfiler tool; but as I said above, I already have my logging module in place. I do not want to use other tool just for logging SQL queries.
How to log/get a SQL query auto-generated by Dapper Extensions without using any other logging tool?
The other similar question is about Dapper. This question is about Dapper Extensions.
Looking at the comment from #MarcGravell and this question about doing the same with Dapper, MiniProfiler.Integrations is better way to implement logging for Dapper Extensions.
Above linked question is about Dapper. But Dapper Extensions uses Dapper internally. So, if logging is implemented for Dapper, same works for Dapper Extensions as well.
More details could be found on GitHub.
Sample code is as below:
var factory = new SqlServerDbConnectionFactory(connectionString);
CustomDbProfiler cp = new CustomDbProfiler();
using(var connection = DbConnectionFactoryHelper.New(factory, cp))
{
//DB Code
}
string log = cp.ProfilerContext.GetCommands();
You can use in-build CustomDbProfiler using CustomDbProfiler.Current if that suits your need. cp.ProfilerContext.GetCommands() will return ALL the commands (success and failed) no matter how many times you call the method. I am not sure but, it might be maintaining concatenated string (StringBuilder may be) internally. If this is the case, this may slow down the performance. But, in my case, logging is disabled by default. I only enable logging when I need to debug something. So this is not a problem for me.
This also may raise memory footprint issue if single connection is used over very large scope. To avoid this, make sure CustomDbProfiler instance is disposed properly.
As mentioned in question, initially, I wanted to avoid this way (using external tool/library). But, MiniProfiler.Integrations is NOT writing the log itself. I can simply get all the queries generated and provide those to my logger module to dump into the file. That is why, this looks more suitable to me now.
MiniProfiler.dll internally implements similar logic (in StackExchange.Profiling.Data.ProfiledDbConnection and StackExchange.Profiling.Data.ProfiledDbCommand classes) which is mentioned here and here. So, if I decide to (in future may be) bypass MiniProfiler, I can use this implementation myself.
Dapper Extensions project is open source; everyone knows that. I downloaded it from GitHub and modified it to meet my needs.
Dapper Extensions build/generate SQL query internally in SqlGeneratorImpl class. There are multiple methods in this class those generate the various queries.
I added following property in DapperExtensions.DapperExtensions static class:
static string lastGeneratedQuery;
public static string LastGeneratedQuery
{
get
{
lock(_lock)
{
return lastGeneratedQuery;
}
}
internal set
{
lock(_lock)
{
lastGeneratedQuery = value;
}
}
}
Also, set this property in various methods of SqlGeneratorImpl class. Following is an example how I set it in Select method.
public virtual string Select(IClassMapper classMap, IPredicate predicate, IList<ISort> sort, IDictionary<string, object> parameters)
{
......
......
StringBuilder sql = new StringBuilder(string.Format("SELECT {0} FROM {1}",
......
......
DapperExtensions.LastGeneratedQuery = sql.ToString();
return sql.ToString();
}
Basic tests run well; I have not yet tested this thoroughly. I will update this answer in case of any change.
Please note that I do not recommend this as standard solution; this is just a hack that works for my needs. I would really like to see this as a regular feature in library. Please post an answer if you have better solution. Otherwise, please comment to improve the solution suggested here.
After merging this pull request in master branch, hopefully this is now available out of the box and no need to download and modify the toolkit source code anymore. Note that I have not verified this.

DevForce enclosing database objects on queries with quotes

I noticed that database queries executed by DevForce encloses database objects in the query with quotes (e.g. select * from "SCHEMA_NAME"."TABLE_NAME"). I'd just like to ask if there is a way for DevForce not to do this.
I'm currently using DevForce Classic 3.7.5.1.
Thanks.
DevForce Classic uses a "provider helper" to determine formatting for a SQL statement. The default helper in use is determined by your connection string, but is usually an instance of OleDbProviderHelper. To change default logic you can subclass either the OleDbProviderHelper, or another of the helpers based on your needs.
In this case, to change formatting for identifiers you can use something similar to the following:
public class CustomProviderHelper : IdeaBlade.Rdb.OleDbProviderHelper {
public override string FormatIdentifier(string identifier) {
return identifier;
}
}
The default logic for this method wraps the identifier with base.IdentifierPrefix and base.IdentifierSuffix values, which you can also override. In the sample above I'm only removing all use of prefixes and suffixes, but you can do whatever works best for you.
DevForce will find your custom implementation if you place the class in an assembly on the server specified as one of the probe assemblies for the RdbKey.

Fill object from SQL result

I have a regular C# class called "vehicle" with properties like Name, NumberPlate, MaxSpeed, etc.
All the data for the class is stored in a SQLite Database where I have a Table "Car" and "Boat". The tables colums have the same names as the class properties (however, there are more columns than class properties - vehicle is a more generic abstraction). At the moment, I have to assign the result of the query individually one by one like this:
while (await statement.StepAsync())
{
myVehicle.Name = statement.Columns["Name"];
//[...]
myVehicle.MaxSpeed = decimal.TryParse(statement.Columns["MaxSpeed"]);
}
Additionally, I have to check if some columns exist ("Car" and "Boat" have a different set of columns) which is more code than I'd like it to be.
I read about EntityFramework to map my db table to my class - but that seems overkill. My requirement is to map properties and columns that have the same name and ignore everything else.
Is there a "easy" (dev time, lines of code) way to map my table columns to my class?
Thanks for reading!
The restrictions in phone 8 mean that a lot of the standard answers to this ("just use {some ORM / micro-ORM}") won't apply, since they don't work on phone 8. You can probably use reflection for a lot of this, but: reflection can be (relatively) slow, so it depends on how much data you will be processing. If it is occasional and light: fine, reflect away.
Runtime meta-programming (the tricks used by libraries like "dapper" in full .NET to make these things really fast) is not available on restricted runtimes, so if you want to avoid lots of boiler-plate that leaves build-time meta-programming. At the simplest, I wonder if you could use something like T4 to automate creating these methods for you as C#. There are also ways to use the reflection-emit API to construct assemblies (at build-time) for phone 8, but that is a pretty hard-core route.
My thoughts:
if the amount of types here isn't huge, just write the code
if you have a lot of types, or you just feel like it, consider a build-time code-generation meta-programming step; you might even think "hmm, is this something I could make available to the community?"
of course, the first thing to do is to check that such a thing doesn't already exist
There is a little helper which might fit your case. Basically, it will take a dictionary and try it's best to populate a objects properties using reflection. I didn't try it by myself though.
You'd simply do something like:
while (await statement.StepAsync())
{
myVehicle = DictionaryToObject<Car>(statement.Columns);
}
It might need some further work to get it running but maybe a good start.

How do I make DRY code using generated WCF proxies from overlapping WSDLs

I have a bunch of WSDLs from our customer describing webservices that I have to use in my application.
There is one webservice for creating items, one for querying them and one for updating them. These WSDLs have a lot of overlap. The items I have to create, query and update are present in all three WSDLs in the same way.
When I use svcutil, I can generate proxies for the three WSDLs, but then every proxy defines the items again. So I have the same class, three times, only in a different namespace.
Working with this forces me to duplicate a lot of code (e.g. mapping a domein object on a proxy class has to be done for every proxy in exactly the same way).
The only solution I can think of is to manually edit the proxies and take out the overlap. However, I think that will make it difficult to manage changes in the web interfaces when I regenerate the proxies.
I wonder if it is possible to somehow generate all the proxies in one go.
Thanks in advance.
You might consider writing a program that parses all the customer WSDLs and stores the operations, etc in a map (or multimap) of some sort. Then iterate over the map and remove the duplicates and write the result to another, final WSDL and codegen on this one. You'll have to do something with the namespaces though.
Something to consider though: would the code needed to do so be more than the extra code you're already duplicating?
Another option could be to define a Proxy class for the duplicated operations. You would have to initialize it by adding the operations with the namespace (create a map of namespace strings to a map of operations, which itself would be the operation strings mapped to the code/object to execute). Then each time you want to perform a specific operation, pass in the namespace string to operate on.
Imagine we had Op1 defined in namespaces ns1, ns2, and ns3 and Op2 in ns1 and ns2. Then the pseudo-code (strongly c++ biased) could be something like:
class ProxyOperations
{
addOperation(string opName, string namespace, OperationBase op);
// You'll have to figure out what to do with the operation parameters,
// maybe wrap them in a parameter context
void doOperation(string opName, string namespace) {
// lookup operation object and execute it
}
typedef map<string, OperationsBase> OperMap;
typedef map<string, operMap> NamespaceMap;
NamespaceMap namespaceOperationMap_;
};
{
ProxyOperations po;
// Populate it
po.addOperation("Op1", "ns1", oper1ObjectNs1);
po.addOperation("Op1", "ns2", oper1ObjectNs2);
po.addOperation("Op1", "ns3", oper1ObjectNs3);
po.addOperation("Op2", "ns1", oper2ObjectNs1);
po.addOperation("Op2", "ns2", oper2ObjectNs2);
// now use it
po.doOperation("Op1", "ns2");
}

What should I do when a class name is very common?

I've just added yet another 3rd-party component to my .net project that contains a class called Client and it got me thinking about common class names.
Do you name your public classes something as common as Client, or do you try to make the name more specific?
In the past I would have said Client was fine, since it can always be accessed explicitly via its namespace (Company.Product.Client) but MS seem to stick to more descriptive class names in the .net framework, such as WebClient, TcpClient and SmtpClient.
I think names like MessagePub.Client look quite neat, and MessagePub.MessagePubClient much less so, but then having lots of Clients floating about also feels quite messy.
All of these 3rd-party components I'm using are actually open source, so is it recommended to refactor and change their class names to something more descriptive to make my code more readable or is accessing via their namespace a better idea? Or does it just not matter? :-)
I think a more descriptive name almost always is better. Its not just a technical issue, but certainly also a semantic one : for one thing it obliges you to think what kind of class you're dealing with exactly and helps you to set the boundaries.
Don't forget about the namespace alias quantifier when you have to deal with third-party libraries using similar/identical names:
using Excel = Microsoft.Office.Interop.Excel;
using Word = Microsoft.Office.Interop.Word;
Like that you can distinguish easily between the different classes:
Excel.Application excelApp = new Excel.Application();
Word.Application wordApp = new Word.Application();
If your identifiers are disambiguated by namespace, Then I can't imagine you should add more noise. As you said, it feels messy.
If its possible for you to have more than one kind of, say, MessagePub.Client, like one that only wants message digests, or one that is a message adapter for some other interface, then of course you would need to clarify that. Perhaps MessagePub.DefaultClient for the common case, MessagePub.DigestClient for the digest consumer, or MessagePub.LogAdaptorClient for the message adaptor
The more descriptive name is a much better idea... because you are going to fund someone with using statements like:
using Company.Product;
using SomeOtherThing.Product;
... and if Client appears in both namespaces, you then have some unreadable code.
Common object names like Client, Product, User, Person, Message, etc... I would almost always prefix with some identifier that reflects their greater purpose.
Well, the more specific the class is a more specifying name it should have - taking into account that it DoesNotGetUnnecessaryLongAndUnhandy.
Of course namespaces are a great method to distiguish namings and add explanatory power to your code. However I wouldn't refactor anything just to have a different naming.
Do you name your public classes something as common as Client, or do you try to make the name more specific?
I try to do two things:
No two of my classes have the same name (but I don't care whether any of my class names collide with a 3rd party's: that's what namespaces are for).
My classes almost never have the same name as any of the Microsoft System classes (I wouldn't create a class called Dictionary or Form, for example)
Client is a poor name, what exactly is it a client of ? I would say that a compound such as MailClient, MicrowaveClient, TelephoneClient etc.

Categories

Resources