When using Ado.Net interfaces such as IDbDataParameter is it correct to still prefix the ParameterName with "#" - sql-server

In a seperate post, Is it necessary to add a # in front of an SqlParameter name?, a discussion is had about prefixing the ParameterName with the "#" sign.
If you are abstracting all of your ADO access behind interfaces such as IDbCommand and using IDbCommand.CreateParameter() to return instances of IDbDataParameter, is it still correct to prefix the ParameterName with "#".
My gut feeling is no, since the # is required by SqlServer and the point of using interfaces to remove the implementation details.
I'd also suggest this is perhaps why the undocumented feature of automatically checking for the prefix character exists, if you are only using ADO.NET via interfaces and are removed from knowing exactly what kind of database you are using ?

Simply as a demonstration that you need to take this little detail into account even when abstracting, if you look at Microsoft's Data Access Block which for years has provided ADO abstraction using the System.Data.Common base, you'll see that they address this very issue by including virtual method in the abstract base class Database that is then overridden by the provider specific derived classes.
So the base class Database.cs has this method:
/// <summary>Builds a value parameter name for the current database.</summary>
/// <param name="name">The name of the parameter.</param>
/// <returns>A correctly formated parameter name.</returns>
public virtual string BuildParameterName(string name){ return name; }
(if the provider uses positional parameters or has no need of a prefix, there is nothing more to override)
and then the SqlClient specific provider implementation SqlDatabase.cs overrides it as such:
/// <summary>Gets the parameter token used to delimit parameters for the SQL Server database.</summary>
protected char ParameterToken{ get { return '#'; } }
public override string BuildParameterName(string name)
{
if (name == null) throw new ArgumentNullException("name");
if (name[0] != ParameterToken)
return name.Insert(0, new string(ParameterToken, 1));
return name;
}
Notice that this implementation allows the calling code to use sql parameter names with the '#' prefix or not, thus freeing the devs from having to know/remember what the api actually does to the name under the covers.
I don't use the DAAB directly, but their overall approach to abstracting behind the System.Data and System.Data.Common interfaces and classes is a great guideline for small data access api's.

Related

What ORM can I use for Access 2007 - 2010? I'm after WPF binding to the tables etc

I've a legacy database that all sites have, it describes specific content in a number of catagory/subcatagory/child item format. Until now, adding/editing the content is either manual work in the tables OR raw sql Windows Forms tool (I built when I started out in the job!).
I would like Entity Framework style drag, drop, bind and run coding ability with WPF 4.5 and .net 4.5.
I hesitate to use NHibernate as EF5 is very simple to get going with, I understand Nhibernate is more work (albeit a faster ORM). Are there alternatives that work well? I'm trying to avoid too much manual setup, if possible. The editor isn't a mandatory project and I can't justify lots of extra work on it - but it would make my job easier for the next 2 years if a nice version of it was put together.
All the argument against Access I know really well :) - swapping this isn't an option for at least a year.
Having searched the StackOverflow site, I don't see too many questions asking for this, but apologies if I've missed a good one!
Update: I think I should refine my question slightly as really what I needed to get at what code generation so that I don't need to hand build all the classes for the Access database. From what I can see, Dapper's work is around efficiency but is distinct from generating code. Coming from a entity framework mindset, I can see where I've conjoined the tasks somewhat in my thinking :). So apart from boil my own - does anyone know a good code gen for use with Access. This I can marry to Dapper :).
You can't use Entity Framework, because it doesn't work with Access databases.
It's possible to use NHibernate with MS Access, although NH doesn't support Access out of the box.
You need NHibernate.JetDriver from NHContrib and here are example settings for the NH config file.
If I recall it correctly, NH Contrib needs to be compiled against the exact NH version you're using, so you probably need to download the source code and compile it by yourself.
As an alternative, you can use one of the many micro-ORMs, for example Stack Overflow's own Dapper.
Dapper is DB agnostic, so it can connect to everything including Access. Quote from the official site:
Will dapper work with my db provider?
Dapper has no DB specific implementation details, it works across all .net ado providers
including sqlite, sqlce, firebird, oracle, MySQL and SQL Server
The disadvantage is that because Dapper is DB agnostic, you have to implement some advanved stuff yourself, like paging.
EDIT:
IMO Dapper is in the "fairly easy to run quickly catagory".
Take a look at this:
(complete demo project here)
using System;
using System.Data.OleDb;
using Dapper;
namespace DapperExample
{
class Program
{
static void Main(string[] args)
{
using (var con = new OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=test.mdb"))
{
var list = con.Query<Product>("select * from products");
Console.WriteLine("map to a strongly typed list:");
foreach (var item in list)
{
Console.WriteLine(item.ProductNumber + " : " + item.Description);
}
Console.WriteLine();
var list2 = con.Query("select * from products");
Console.WriteLine("map to a list of dynamic objects:");
foreach (var item in list2)
{
Console.WriteLine(item.ProductNumber + " : " + item.Description);
}
Console.ReadLine();
}
}
}
public class Product
{
public string ProductNumber { get; set; }
public string Description { get; set; }
}
}
There are two different queries in this example code.
The first one maps to a strongly typed list, e.g. the result is an IEnumerable<Product>. Of course it needs a Product class that it can map to.
The second query returns an IEnumerable<Dynamic> (>= .NET 4.0) which means that the properties are evaluated on the fly and you don't need to define a class before, but the disadvantage is that you lose type safety (and IntelliSense).
My personal opinion is that the missing type safety is a deal breaker for me (I prefer the first query syntax), but maybe this is something for you.
Hate to resurrect an old thread but I recently did a WPF project using PetaPoco, a micro-ORM, with MS Access so I thought I'd share my implementation.
To add MS Access support to PetaPoco, you just need to add a couple of bits of code:
First add an AccessDatabaseType class. All of the DataBaseType classes are at the end of the PetaPoco.cs file. Just add the new class after SqlServerDatabaseType.
class AccessDatabaseType : DatabaseType
{
public override object ExecuteInsert(Database db, IDbCommand cmd, string PrimaryKeyName)
{
db.ExecuteNonQueryHelper(cmd);
return db.ExecuteScalar<object>("SELECT ###IDENTITY AS NewID;");
}
}
Next, modify PetaPoco.Internal.DatabaseType.Resolve() to support the AccessDatabaseType. (This code assumes you are using the Jet OLEDB provider)
public static DatabaseType Resolve(string TypeName, string ProviderName)
{
//...
if (ProviderName.IndexOf("Oledb", StringComparison.InvariantCultureIgnoreCase) >= 0)
return Singleton<AccessDatabaseType>.Instance;
// Assume SQL Server
return Singleton<SqlServerDatabaseType>.Instance;
}
Finally, to instantiate PetaPoco use this:
Db = New PetaPoco.Database("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\db.mdb", "System.Data.Oledb")
Limitations:
PetaPoco assumes your primary keys are autonumber/identity fields. If you have a PK that's not an autonumber or you have a composite PK, you'll need to implement your own insert & save logic.
I didn't need paging in my application so I didn't implement it.
We are using
Jet Entity Framework Provider. That way we can easily port to another database later.
It does not have all the limitations mentioned above and works great.
Tortuga Chain fully supports Access.
https://docevaad.github.io/Chain/Introduction.htm

ADO.NET EF + CF: How to use the existing CF context and bind SQL external objects (views, stored procedures, etc.)?

I have a database, 90% created with EF 4.1 + Code First approach on a SQL Server 2012; the rest is generated by some SQL code (FUNCTIONS, COMPUTED COLUMNS, VIEWS, INDEXES, ETC.).
Now, I needed to use ObjectContext and at the same time optimize performance, so I created some SQL Views directly in the db, which basically do some calculations (count, mix, sum, etc.) on the already CF's generated tables.
I'd like to use the above "external" SQL views inside my solution, possibly pointing to the same connectionstring of my CF context and using with the same repository I created.
I succeed to make an ADO.NET EDM of the Views (is this the right approach?), so now I have the Entity Model generated from db.
For the reasons described above, in first instance I used the existing data connection and I choose to do not save the additional connection string inside my web.config.
Now I have the edmx containing myModel and myModel.Store of the "external" views. For example, here's an extract of mymodel.Designer.cs, which seems to be the standard one I've seen in other edmx of other projects:
public partial class Entities : ObjectContext
{
#region Constructors
/// <summary>
/// Initializes a new Entities object using the connection string found in the 'Entities' section of the application configuration file.
/// </summary>
public Entities() : base("name=Entities", "Entities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
/// <summary>
/// Initialize a new Entities object.
/// </summary>
public Entities(string connectionString) : base(connectionString, "Entities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
/// <summary>
/// Initialize a new Entities object.
/// </summary>
public Entities(EntityConnection connection) : base(connection, "Entities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
#endregion
.............
I'd like to query the "external" entities. I did several tests, but I did not succeed.
Could you tell me the right approach to the problem, please?
1) This is one of the tests I made. In this case I get an exception "The specified named connection is either not found in the configuration, not intended to be used with the EntityClient provider, or not valid":
public class TManagerRepository : ITManagerRepository, IDisposable
{
private TManagerContext context; // the context pointing to CF entities
private TManager.Models.Entities.SQL_Views.Entities entities; // the context pointing to the SQL views by the EDM
public TManagerRepository(TManagerContext context)
{
this.context = context;
this.entities = new TManager.Models.Entities.SQL_Views.Entities();
var test = (from d in this.entities.myview
select d);
}
2) Then I tried to make a specific connection too, but I get an exception which says "Could not find the conceptual model to validate".
Thank you very much for your precious help!
Best Regards
You cannot use same connection string for code first approach and for EDMX. Required connection strings have different format. So if you don't want to store connection string for EDMX context in your configuration file you must to built it manually.

Parameter must be an entity type exposed by the DomainService?

Trying to implement a domain service in a SL app and getting the following error:
Parameter 'spFolderCreate' of domain method 'CreateSharePointFolder' must be an entity type exposed by the DomainService.
[EnableClientAccess()]
public class FileUploadService : DomainService
{
public void CreateSharePointFolder(SharePointFolderCreate spFolderCreate)
{
SharePointFolder spf = new SharePointFolder();
spf.CreateFolder_ClientOM(spFolderCreate.listName, spFolderCreate.fileName);
}
[OperationContract]
void CreateSharePointFolder(SharePointFolderCreate spFolderCreate);
[DataContract]
public class SharePointFolderCreate
{
private string m_listName;
private string m_fileName;
[DataMember]
public string listName
{
get { return m_listName; }
set { m_listName = value; }
}
[DataMember]
public string fileName
{
get { return m_fileName; }
set { m_fileName = value; }
}
}
So am I missing something simple here to make this all work?
It may be that the framework is inferring the intended operation because you have the word "Create" prefixing the function name (CreateSharePointFolder). Details of this behaviour can be found here
Although that is all fine for DomainServices and EntityFramework, following the information in that article, it can be inferred that methods beginning "Delete" will be performing a delete of an entity, so must accept an entity as a parameter. The same is true for "Create" or "Insert" prefixed methods. Only "Get" or "Select" methods can take non-entity parameters, making it possible to pass a numeric id (for example) to a "Get" method.
Try changing your method name temporarily to "BlahSharePointFolder" to see if it is this convention of inferrance that's causing your problem.
Also, as there is no metadata defined for your SharePointFolderCreate DC, you might need to decorate the class (in addition to the [DataContract] attribute) with the [MetadataType] attribute. You will see how to implement this if you used the DomainServiceClass wizard and point to an EF model. There is a checkbox at the bottom for generating metadata. Somewhere in your solution.Web project you should find a domainservice.metadata.cs file. In this file, you will find examples of how to use the [MetadataType] attribute.
For the RIA WCF service to work correctly with your own methods, you need to ensure that all entities existing on the parameter list have at least one member with a [Key] attribute defined in their metadata class, and that the entity is returned somewhere on your DomainService in a "Get" method.
HTH
Lee

Entity Framework 4 - Trim Database Char(50) value for Name on legacy database

This should be simple, but I haven't found a way yet...
I have a legacy database with name fields that are stored as CHAR(50). When this is bound to a TextBox with a Max Length of 50, you cannot insert.
How can I make the EF trim these values or at least map to RTrim(Column)?
I've tried using value converters, but the round trip causes issues with back spacing and spaces getting deleted between words.
Note that I only want to trim some fields, not all.
We are using SQL Server 2000 as the database. Soon to move to SQL 2008.
Thanks!
Entity framework is able to map only to table directly. You can also map to view or custom DB query but in such case your entity will became readonly unless you also map Insert, Delete and Update operations to stored procedures.
I think the problem you describes is related to ANSI PADDING behavior. It can be turned on but:
It is not recommended. In future version of SQL server it will be considered as error.
Must be configured before you create a column
You must handle trimming in the application. You can for example modify T4 template (if you use them) to trim string properties. Not sure how it works with WPF but you probably can inherit text box and override Text property to trim values.
Another way is handling ObjectMaterialized event on ObjectContext and manually trimming text properties but it can slow down your execution of your queries.
There's no way to do this with EF and SQL Server that I have found. I solved it with an extension method on IEnumerable<T> that calls TrimEnd() on each string property:
public static IEnumerable<TEntity> Trim<TEntity>(this IEnumerable<TEntity> collection)
{
Type type = typeof(TEntity);
IEnumerable<PropertyDescriptor> properties = TypeDescriptor.GetProperties(type).Cast<PropertyDescriptor>()
.Where(p => p.PropertyType == typeof(string));
foreach (TEntity entity in collection)
{
foreach (PropertyDescriptor property in properties)
{
string value = (string) property.GetValue(entity);
if (!String.IsNullOrEmpty(value))
{
value = value.TrimEnd();
property.SetValue(entity, value);
}
}
}
return collection;
}
Just make sure you call it after EF has retrieved the entities from the database. For example, after ToList():
public IEnumerable<Country> FetchCountries()
{
return _context.Set<Country>().ToList().Trim();
}
Have a look at the available attributes for your Database Connection String. I had a similar issue with Sybase Advantage database and solved with it's TrimTrailingSpaces attribute. Your database may support something similar.
Data Source=\\serverx\volumex\path\db.add;User ID=user;Password=pass;ServerType=REMOTE;TrimTrailingSpaces=TRUE;
http://www.connectionstrings.com/

.net propertychange notification handlers - strings vs. expressions

Using WPF has made me a fan of INotifyPropertyChanged. I like to use a helper that takes an expression and returns the name as a string (see example code below). In lots of applications I see by very proficient programmers, however, I see code that handles the strings raw (see 2nd example below). By proficient I mean MVP types who know how to use Expressions.
To me, the opportunity for having the compiler catch mistakes in addition to easy refactoring makes the Exression approach better. Is there an argument in favor of using raw strings that I am missing?
Cheers,
Berryl
Expression helper example:
public static string GetPropertyName<T>(Expression<Func<T, object>> propertyExpression)
{
Check.RequireNotNull<object>(propertyExpression, "propertyExpression");
switch (propertyExpression.Body.NodeType)
{
case ExpressionType.MemberAccess:
return (propertyExpression.Body as MemberExpression).Member.Name;
case ExpressionType.Convert:
return ((propertyExpression.Body as UnaryExpression).Operand as MemberExpression).Member.Name;
}
var msg = string.Format("Expression NodeType: '{0}' does not refer to a property and is therefore not supported",
propertyExpression.Body.NodeType);
Check.Require(false, msg);
throw new InvalidOperationException(msg);
}
Raw strings example code (in some ViewModelBase type class):
/// <summary>
/// Warns the developer if this object does not have
/// a public property with the specified name. This
/// method does not exist in a Release build.
/// </summary>
[Conditional("DEBUG"), DebuggerStepThrough]
public void VerifyPropertyName(string propertyName) {
// Verify that the property name matches a real,
// public, instance property on this object.
if (TypeDescriptor.GetProperties(this)[propertyName] == null) {
string msg = "Invalid property name: " + propertyName;
if (ThrowOnInvalidPropertyName) throw new Exception(msg);
else Debug.Fail(msg);
}
}
/// <summary>
/// Returns whether an exception is thrown, or if a Debug.Fail() is used
/// when an invalid property name is passed to the VerifyPropertyName method.
/// The default value is false, but subclasses used by unit tests might
/// override this property's getter to return true.
/// </summary>
protected virtual bool ThrowOnInvalidPropertyName { get; private set; }
To me, the opportunity for having the compiler catch mistakes in addition to easy refactoring makes the Exression approach better. Is there an argument in favor of using raw strings that I am missing?
I agree, and personally, use the expression approach in my own code, in most cases.
However, there are two reasons I know of to avoid this:
It is less obvious, especially to less experienced .NET developers. Writing RaisePropertyChanged(() => this.MyProperty ); is not always as obvious to people as RaisePropertyChanged("MyProperty");, and doesn't match framework samples, etc.
There is some performance overhead to using expressions. Personally, I don't feel this is really that meaningful of a reason, since this is usually used in data binding scenarios (which are already slow due to reflection usage), but it is potentially a valid concern.
The benefit of using the TypeDescriptor approach is that it enables dynamic property scenarios based on ICustomTypeDescriptor implementations where the implementation can effectively create dynamic property metadata on the fly for a type that is being described. Consider a DataSet whose "properties" are determined by the result set it is populated with for example.
This is something that expressions does not provide however because it's based on actual type information (a good thing) as opposed to strings.
I wound up spending more time on this than I expected, but did find a solution that has a nice mix of safety/refactorability and performance. Good background reading and an alternate solution using reflection is here. I like Sacha Barber's solution even better (background here.
The idea is to use an expression helper for a property that will participate in change notification, but only take the hit once for it, by storing the resulting PropertyChangedEventArgs in your view model. For example:
private static PropertyChangedEventArgs mobilePhoneNumberChangeArgs =
ObservableHelper.CreateArgs<CustomerModel>(x => x.MobilePhoneNumber);
HTH,
Berryl
Stack walk is slow and lambda expression is even slower. We have solution similar to well known lambda expression but almost as fast as string literal. See
http://zamboch.blogspot.com/2011/03/raising-property-changed-fast-and-safe.html
A CallerMemberName attribute was introduced in .net 4.5
This attribute can only be attached to optional string parameters and if the parameter is not used by caller in the function call then name of the caller will be passed in the string parameter
This removes the need to specify name of property when raising the PropertyChanged event thus it works with refactoring and because the changes are done at compile time there's no difference in performance.
Below is an example of implementation and more info can be found at http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.callermembernameattribute.aspx and http://msdn.microsoft.com/en-us/library/hh534540.aspx
public class DemoCustomer : INotifyPropertyChanged
{
string _customerName
public string CustomerName
{
get { return _customerNameValue;}
set
{
if (value != _customerNameValue)
{
_customerNameValue = value;
NotifyPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

Resources