We have a C# Windows Phone application and I am trying to make use of dbschemaupdater.AddIndex().
However, I am unsure of how to define the fields associated with the index and cannot find any online examples that seem relevant.
Our database tables are defined as classes via SQLMetal, e.g.
[global::System.Data.Linq.Mapping.TableAttribute(Name = "PDA_AppActiveLog")]
public partial class PDA_AppActiveLog : INotifyPropertyChanging, INotifyPropertyChanged
{
private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
[Column(IsVersion = true)]
private Binary version;
private int _AppActiveLogID;
private DateTime _EventTime;
private string _EventCode;
#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnAppActiveLogIDChanging(int value);
partial void OnAppActiveLogIDChanged();
partial void OnEventTimeChanging(DateTime value);
partial void OnEventTimeChanged();
partial void OnEventCodeChanging(string value);
partial void OnEventCodeChanged();
#endregion
public PDA_AppActiveLog()
{
OnCreated();
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_AppActiveLogID", AutoSync = AutoSync.OnInsert, DbType = "Int NOT NULL IDENTITY", IsPrimaryKey = true, IsDbGenerated = true)]
public int AppActiveLogID
{
get
{
return this._AppActiveLogID;
}
set
{
if ((this._AppActiveLogID != value))
{
this.OnAppActiveLogIDChanging(value);
this.SendPropertyChanging();
this._AppActiveLogID = value;
this.SendPropertyChanged("AppActiveLogID");
this.OnAppActiveLogIDChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_EventTime", DbType = "DateTime NOT NULL", CanBeNull = false)]
public DateTime EventTime
{
get
{
return this._EventTime;
}
set
{
if ((this._EventTime != value))
{
this.OnEventTimeChanging(value);
this.SendPropertyChanging();
this._EventTime = value;
this.SendPropertyChanged("EventTime");
this.OnEventTimeChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_EventCode", DbType = "NVarChar(30)", UpdateCheck = UpdateCheck.Never, CanBeNull = true)]
public string EventCode
{
get
{
return this._EventCode;
}
set
{
if ((this._EventCode != value))
{
this.OnEventCodeChanging(value);
this.SendPropertyChanging();
this._EventCode = value;
this.SendPropertyChanged("EventCode");
this.OnEventCodeChanged();
}
}
}
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanging()
{
if ((this.PropertyChanging != null))
{
this.PropertyChanging(this, emptyChangingEventArgs);
}
}
protected virtual void SendPropertyChanged(String propertyName)
{
if ((this.PropertyChanged != null))
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Within our code, we add something like:
if (dbSchema.DatabaseSchemaVersion == 8)
{
dbSchema.AddTable<PDA_AppActiveLog>();
dbSchema.DatabaseSchemaVersion = 9;
//dbSchema.AddIndex<PDA_AppActiveLog>("EventCode");
dbSchema.Execute();
dbSchema = dc.CreateDatabaseSchemaUpdater();
}
However, I am unsure how to define which fields belong to the new index.
It seems from this article, that the functionality is there:
http://justinangel.net/AllWp7MangoAPIs#linq2sql
However, all the examples I've seen show the database definition code differently, e.g.:
http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh394022(v=vs.105).aspx#BKMK_Preparingversion3Addinganindexconsideringmultipleupgradepaths
// Index added in version 3 of the application.
[Index(Columns = "Priority", Name = "PriorityIndex")]
I am unsure if I can make equivalent changes, but even if I am, then I can no longer use SQLMetal to pre-generate the classes unless I want to modify them everytime afterwards?
What is the best way to get an index added?
Thanks.
Related
I think I'm missing something fundamental when implementing a LinqToHql generator class.
I've successfully registered the SQL Server 2008 contains query using a custom dialect with this registration:
RegisterFunction("contains", new StandardSQLFunction("contains", null));
I have only one class with a full text index to be queried:
public class SearchName
{
public virtual Guid Id {get; set;}
public virtual string Name {get; set;} // this is the search field
}
The contains function works properly in HQL:
var names = Session.CreateQuery("from SearchName where contains(Name,:keywords)")
.SetString("keywords", "john")
.List();
and the generated SQL is perfect:
select searchname0_.Id as Id4_,
searchname0_.Name as Name4_
from Search_Name searchname0_
where contains(searchname0_.Name, 'john' /* #p0 */)
The next challenge was to implement the Linq to HQL generator:
public class MyLinqtoHqlGeneratorsRegistry :
DefaultLinqToHqlGeneratorsRegistry
{
public MyLinqtoHqlGeneratorsRegistry()
{
this.Merge(new ContainsGenerator());
}
}
public class ContainsGenerator : BaseHqlGeneratorForMethod
{
public ContainsGenerator()
{
SupportedMethods = new[] {
ReflectionHelper.GetMethodDefinition<SearchName>(d => d.Name.Contains(String.Empty))
};
}
public override HqlTreeNode BuildHql(MethodInfo method,
System.Linq.Expressions.Expression targetObject,
ReadOnlyCollection<System.Linq.Expressions.Expression> arguments,
HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
return treeBuilder.MethodCall("contains",
visitor.Visit(targetObject).AsExpression(),
visitor.Visit(arguments[0]).AsExpression()
);
}
}
}
Calling the method like this:
var namesLinq = Session.Query<SearchName>().Where(x=> x.Name.Contains("john")).ToList();
Unfortunately, this doesn't seem to override the built-in Contains method, and the generated SQL is wrong:
select searchname0_.Id as Id4_,
searchname0_.Name as Name4_
from Search_Name searchname0_
where searchname0_.Name like ('%' + 'john' /* #p0 */ + '%')
Is it not possible to override the default Contains method, or have I just made a silly mistake?
PS - I'm using NHibernate 3.3.1.4000
OK, I've finally figured it out!
First, I managed to delete the registration code from my configuration:
...
.ExposeConfiguration(cfg =>
{
cfg.LinqToHqlGeneratorsRegistry<MyLinqtoHqlGeneratorsRegistry>();
...
}
Second, don't try to override the existing Linq behaviors. I moved my Contains extension method to the full-text class.
Third, build the Hql tree correctly.
For others trying to implement a SQL 2008 Free-text contains search, here's the complete implementation:
public static class DialectExtensions
{
public static bool Contains(this SearchName sn, string searchString)
{
// this is just a placeholder for the method info.
// It does not otherwise matter.
return false;
}
}
public class MyLinqtoHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
public MyLinqtoHqlGeneratorsRegistry()
: base()
{
RegisterGenerator(ReflectionHelper.GetMethod(() =>
DialectExtensions.Contains(null, null)),
new ContainsGenerator());
}
}
public class ContainsGenerator : BaseHqlGeneratorForMethod
{
string fullTextFieldName = "Name";
public ContainsGenerator()
: base()
{
SupportedMethods = new[] {
ReflectionHelper.GetMethodDefinition(() =>
DialectExtensions.Contains(null, null))
};
}
public override HqlTreeNode BuildHql(MethodInfo method,
System.Linq.Expressions.Expression targetObject,
ReadOnlyCollection<System.Linq.Expressions.Expression> arguments,
HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
// cannot figure out how to interrogate the model class to get an
// arbitrary field name...
// perhaps the RegisterGenerator() call above could be used to pass a
// property name to the ContainsGenerator constructor?
// in our case, we only have one full text searchable class, and its
// full-text searchable field is "Name"
HqlExpression[] args = new HqlExpression[2] {
treeBuilder.Ident(fullTextFieldName).AsExpression(),
visitor.Visit(arguments[1]).AsExpression()
};
return treeBuilder.BooleanMethodCall("contains", args);
}
}
For the above to work, you must have declared and used your custom dialect:
public class CustomMsSql2008Dialect : NHibernate.Dialect.MsSql2008Dialect
{
public CustomMsSql2008Dialect()
{
RegisterFunction(
"contains",
new StandardSQLFunction("contains", null)
);
}
}
Then you can use your new contains search this way:
var namesLinq = Session.Query<SearchName>().Where(x => x.Contains("john")).ToList();
... and the resulting SQL is perfect! (at least if you only have one table you're performing full-text searches on)
EDIT: UPDATED IMPLEMENTATION TO SUPPORT MORE THAN ONE FULLTEXT 'Contains' SEARCH PER QUERY.
Here's the revised version:
public static class DialectExtensions
{
public static bool FullTextContains(this string source, string pattern)
{
return false;
}
}
public class MyLinqtoHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
public MyLinqtoHqlGeneratorsRegistry()
: base()
{
RegisterGenerator(ReflectionHelper.GetMethod(() => DialectExtensions.FullTextContains(null, null)),
new FullTextContainsGenerator());
}
}
public class FullTextContainsGenerator : BaseHqlGeneratorForMethod
{
public FullTextContainsGenerator()
{
SupportedMethods = new[] { ReflectionHelper.GetMethod(() => DialectExtensions.FullTextContains(null, null)) };
}
public override HqlTreeNode BuildHql(MethodInfo method,
System.Linq.Expressions.Expression targetObject,
ReadOnlyCollection<System.Linq.Expressions.Expression> arguments,
HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
HqlExpression[] args = new HqlExpression[2] {
visitor.Visit(arguments[0]).AsExpression(),
visitor.Visit(arguments[1]).AsExpression()
};
return treeBuilder.BooleanMethodCall("contains", args);
}
}
To use the revised version, the syntax is slightly different:
var namesLinq = Session.Query<SearchName>().Where(x => x.Name.FullTextContains("john")).ToList();
I have three MvxSpinners in my android view.
These spinners are binded to three different lists.
and Mode of data binding is TwoWay for these spinners.i.e. when this view is
displayed,all of these three spinners are get displayed with the predefined values.
When user change the value in first spinner,then second spinner will be clear and
get loaded with new values based on the selected value in first spinner.
How can I achieve this?
There's many ways to accomplish this, where the code placement is really up to you. Overall the idea would be to have a "SelectedItem" object that you can pass into your method and "Load" the next List.
Please keep in mind that this code is more traditional MVVM, but can easily be converted to MVVMCross equivalent. I believe all these types should be supported by MVVMCross.
private MyFirstObject _selectedFirstObject;
public MyFirstObject SelectedFirstObject
{
get { return _selectedFirstObject; }
set
{
_selectedFirstObject = value;
RaisePropertyChanged("SelectedFirstObject");
if(value != null)
LoadMySecondObjects(value);
}
}
private ObservableCollection<MyFirstObject> _myFirstObjects;
public ObservableCollection<MyFirstObject> MyFirstObjects
{
get { return _myFirstObjects; }
set
{
_myFirstObjects = value;
RaisePropertyChanged("MyFirstObjects");
}
}
private ObservableCollection<MySecondObject> _mySecondObjects;
public ObservableCollection<MySecondObject> MySecondObjects
{
get { return _mySecondObjects; }
set
{
_mySecondObjects = value;
RaisePropertyChanged("MySecondObjects");
}
}
public void LoadMySecondObjects(MyFirstObject current)
{
//Wherever you're pulling data from
MySecondObjects = MyDataService.GetAll(current);
}
protected void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
I had the same problem but only if you add null value (as a default value) to your ItemsSource and try to reset SelectedItem to null. SelectedItem is changed in ViewModel but not in the spinner. In that case there's number of solutions but I used message to inform View to set selected item
public class SpinnerSelectionChanged : MvxMessage
{
public SpinnerSelectionChanged(object sender, string spinnerName, int position): base(sender)
{
SpinnerName = spinnerName;
Position = position;
}
public string SpinnerName { get; set; }
public int Position { get; set; }
}
in View
private void OnSpinnerSelectionChanged(SpinnerSelectionChanged obj)
{
switch (obj.SpinnerName)
{
case "City":
_spinnerCity.SetSelection(obj.Position);
break;
case "Office":
_spinnerOffice.SetSelection(obj.Position);
break;
}
}
I am working on upgrading our project from .Net 2 to .Net4.5, at the same time I'm pushing as many references as I can to NuGet and making sure the versions are current.
I am having a problem getting one of the tests to run
The Test Classes:
public class Person
{
public static int PersonBaseMethodHitCount { get; set; }
public virtual void BaseMethod()
{
PersonBaseMethodHitCount = PersonBaseMethodHitCount + 1;
}
public static int PersonSomeMethodToBeOverriddenHitCount { get; set; }
public virtual void SomeMethodToBeOverridden()
{
PersonSomeMethodToBeOverriddenHitCount = PersonSomeMethodToBeOverriddenHitCount + 1;
}
}
public class Employee : Person
{
public static int EmployeeSomeMethodToBeOverriddenHitCount { get; set; }
public override void SomeMethodToBeOverridden()
{
EmployeeSomeMethodToBeOverriddenHitCount = EmployeeSomeMethodToBeOverriddenHitCount + 1;
}
public static int EmployeeCannotInterceptHitCount { get; set; }
public void CannotIntercept()
{
EmployeeCannotInterceptHitCount = EmployeeCannotInterceptHitCount + 1;
}
public virtual void MethodWithParameter(
[SuppressMessage("a", "b"), InheritedAttribute, Noninherited]string foo)
{
}
}
public class MyInterceptor : IInterceptor
{
public static int HitCount { get; set; }
public void Intercept(IInvocation invocation)
{
HitCount = HitCount + 1;
invocation.Proceed();
}
}
The test (there is no setup for this fixture):
var container = new WindsorContainer();
container.Register(Component.For<MyInterceptor>().ImplementedBy<MyInterceptor>());
container.Register(
Component
.For<Employee>()
.ImplementedBy<Employee>()
.Interceptors(InterceptorReference.ForType<MyInterceptor>())
.SelectedWith(new DerivedClassMethodsInterceptorSelector()).Anywhere);
container.Register(Classes.FromAssembly(Assembly.GetExecutingAssembly()).Pick().WithService.FirstInterface());
var employee = container.Resolve<Employee>();
Person.PersonBaseMethodHitCount = 0;
Person.PersonSomeMethodToBeOverriddenHitCount = 0;
Employee.EmployeeCannotInterceptHitCount = 0;
Employee.EmployeeSomeMethodToBeOverriddenHitCount = 0;
MyInterceptor.HitCount = 0;
employee.BaseMethod();
Assert.That(Person.PersonBaseMethodHitCount, Is.EqualTo(1));
// The BaseMethod was not overridden in the derived class so the interceptor should not have been called.
Assert.That(MyInterceptor.HitCount, Is.EqualTo(0));
Person.PersonBaseMethodHitCount = 0;
Person.PersonSomeMethodToBeOverriddenHitCount = 0;
Employee.EmployeeCannotInterceptHitCount = 0;
Employee.EmployeeSomeMethodToBeOverriddenHitCount = 0;
MyInterceptor.HitCount = 0;
employee.SomeMethodToBeOverridden();
Assert.That(Person.PersonSomeMethodToBeOverriddenHitCount, Is.EqualTo(0));
Assert.That(Employee.EmployeeSomeMethodToBeOverriddenHitCount, Is.EqualTo(1));
Assert.That(MyInterceptor.HitCount, Is.EqualTo(1)); //The test errors out on this line
Person.PersonBaseMethodHitCount = 0;
Person.PersonSomeMethodToBeOverriddenHitCount = 0;
Employee.EmployeeCannotInterceptHitCount = 0;
Employee.EmployeeSomeMethodToBeOverriddenHitCount = 0;
MyInterceptor.HitCount = 0;
employee.CannotIntercept();
Assert.That(Employee.EmployeeCannotInterceptHitCount, Is.EqualTo(1));
Assert.That(MyInterceptor.HitCount, Is.EqualTo(0));
I added a comment to denote where the test fails.
So far as I can tell the problem is arising in the DerivedClassMethodsInterceptorSelector
Selector:
public class DerivedClassMethodsInterceptorSelector : IInterceptorSelector
{
public IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors)
{
return method.DeclaringType != type ? new IInterceptor[0] : interceptors;
}
}
When it makes the comparison of types, the type variable is System.RuntimeType but should be Employee (at least this is my understanding).
EDIT:
This problem was occurring using Castle.Windsor and Castle.Core 3.2.1, After making NuGet install the 3.1.0 package the code works as expected.
I am leaning towards this being a bug, but I could also just be a change in the logic.
I was able to reproduce the same issue with version 3.3.3 with this simple unit test:
[TestClass]
public class MyUnitTest
{
[TestMethod]
public void BasicCase()
{
var ProxyFactory = new ProxyGenerator();
var aopFilters = new IInterceptor[] {new TracingInterceptor()};
var ConcreteType = typeof(MyChild);
var options = new ProxyGenerationOptions { Selector = new AopSelector() };
var proxy = ProxyFactory.CreateClassProxy(ConcreteType, options, aopFilters) as MyChild;
proxy.DoIt();
}
}
public class AopSelector : IInterceptorSelector
{
public IInterceptor[] SelectInterceptors(Type runtimeType, MethodInfo method, IInterceptor[] interceptors)
{
Assert.IsTrue(runtimeType == typeof(MyChild));
return interceptors;
}
}
public class MyWay
{
public virtual void DoIt()
{
Thread.Sleep(200);
}
}
public class MyChild : MyWay
{
public virtual void DoIt2()
{
Thread.Sleep(200);
}
}
public class TracingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
var isProperty = invocation.Method.Name.StartsWith("get_")
|| invocation.Method.Name.StartsWith("set_");
if (isProperty)
{
invocation.Proceed();
return;
}
LogMethod(invocation);
}
protected virtual void LogMethod(IInvocation invocation)
{
var target = (invocation.InvocationTarget ?? invocation.Proxy).GetType().Name;
var stopwatch = Stopwatch.StartNew();
try
{
stopwatch.Start();
invocation.Proceed();
}
finally
{
stopwatch.Stop();
var result = stopwatch.ElapsedMilliseconds;
}
}
}
I fixed it by changing Castle's source code and editing method TypeUtil.GetTypeOrNull to look like this:
public static Type GetTypeOrNull(object target)
{
if (target == null)
{
return null;
}
var type = target as Type;
if (type != null)
{
return type;
}
return target.GetType();
}
Of course this is a naive fix, because the problem is somewhere else and it is that instead of an object instance passed to this method, its Type is passed in. However checking if the passed parameter is of type Type and if so returning it instead of calling GetType on it makes it work.
public IEnumerable<T> ExecuteStoredProcedure<T>(params object[] parameters)
{
Type genericType = typeof(T);
string commandthing = genericType.Name.Replace("Result", "");
//_db is my Linq To Sql database
return _db.ExecuteQuery<T>(commandthing, parameters).AsEnumerable();
}
The stored procedure is named GetOrder and has a single int parameter of orderid. I'm calling the above like so:
SqlParameter parm1 = new SqlParameter("#orderid", SqlDbType.Int);
parm1.Value = 123;
var results =
_session.ExecuteStoredProcedure<GetOrderResult>(parm1).Single();
I'm receiving the following error: A query parameter cannot be of type 'System.Data.SqlClient.SqlParameter'
Thoughts? Or am I just missing something obvious?
Update: I'm trying to make this as generic as possible...my current thinking is that I'm going to have to do some string trickery to create the ExecuteQuery text and parameters.
Update: Posting below my Session Interface and my Linq to Sql Implementation of the interface...hopefully that will clarify what I'm attempting to do
public interface ISession : IDisposable
{
void CommitChanges();
void Delete<T>(Expression<Func<T, bool>> expression) where T : class;
void Delete<T>(T item) where T : class;
void DeleteAll<T>() where T : class;
T Single<T>(Expression<Func<T, bool>> expression) where T : class;
IQueryable<T> All<T>() where T : class;
void Add<T>(T item) where T : class;
void Add<T>(IEnumerable<T> items) where T : class;
void Update<T>(T item) where T : class;
IEnumerable<T> ExecuteStoredProcedure<T>(params object[] parameters);
}
public class LinqToSqlSession : ISession
{
public readonly Db _db;
public LinqToSqlSession()
{
_db = new Db(ConfigurationManager.ConnectionStrings[Environment.MachineName].ConnectionString);
}
public void CommitChanges()
{
_db.SubmitChanges();
}
/// <summary>
/// Gets the table provided by the type T and returns for querying
/// </summary>
private Table<T> GetTable<T>() where T : class
{
return _db.GetTable<T>();
}
public void Delete<T>(Expression<Func<T, bool>> expression) where T : class
{
var query = All<T>().Where(expression);
GetTable<T>().DeleteAllOnSubmit(query);
}
public void Delete<T>(T item) where T : class
{
GetTable<T>().DeleteOnSubmit(item);
}
public void DeleteAll<T>() where T : class
{
var query = All<T>();
GetTable<T>().DeleteAllOnSubmit(query);
}
public void Dispose()
{
_db.Dispose();
}
public T Single<T>(Expression<Func<T, bool>> expression) where T : class
{
return GetTable<T>().SingleOrDefault(expression);
}
public IEnumerable<T> ExecuteStoredProcedure<T>(params object[] parameters)
{
Type genericType = typeof(T);
string commandstring = genericType.Name.Replace("Result", "");
//_db is my Linq To Sql database
return _db.ExecuteQuery<T>(commandstring, parameters).AsEnumerable();
}
public IQueryable<T> All<T>() where T : class
{
return GetTable<T>().AsQueryable();
}
public void Add<T>(T item) where T : class
{
GetTable<T>().InsertOnSubmit(item);
}
public void Add<T>(IEnumerable<T> items) where T : class
{
GetTable<T>().InsertAllOnSubmit(items);
}
public void Update<T>(T item) where T : class
{
//nothing needed here
}
}
That isn't how you're supposed to wire up Stored Procedures with Linq-to-SQL. You should extend the DataContext and use ExecuteMethodCall instead:
Taken from MSDN:
public partial class MyDataContext
{
[Function()]
public IEnumerable<Customer> CustomerById(
[Parameter(Name = "CustomerID", DbType = "NChar(5)")]
string customerID)
{
IExecuteResult result = this.ExecuteMethodCall(this,
((MethodInfo)(MethodInfo.GetCurrentMethod())),
customerID);
return (IEnumerable<Customer>)(result.ReturnValue);
}
}
If you really must execute a sproc as a query (highly not recommended), then you have to preface the command with EXEC, and don't use SqlParameter either, the call would look like:
var results = context.ExecuteQuery<MyResult>("EXEC usp_MyProc {0}, {1}",
custID, custName);
(And I'll note, pre-emptively, that this is not a SQL injection vector because Linq to SQL turns the curly braces into a parameterized query.)
Read about how to call sprocs in linq to sql
http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx
Had the same Problem. The following approach worked 4 me.
public interface IBusinessEntityRepository
{
.......
object CallStoredProcedure(string storedProcedureName, object[] parameters);
}
implementation in my linqtosql GenericLinqRepository
public object CallStoredProcedure(string storedProcedureName, object[] parameters)
{
DataContext dataContext = GetCurrentDataContext();
MethodInfo method = dataContext.GetType().GetMethod(storedProcedureName);
return method.Invoke(dataContext, parameters);
}
I'm sure there is a better way to do this...but this is presently working:
public IEnumerable<T> ExecuteStoredProcedure<T>(params object[] parameters)
{
Type genericType = typeof(T);
StringBuilder sb=new StringBuilder();
sb.Append("EXEC ");
sb.Append(genericType.Name.Replace("Result", " " ));
for (int i = 0; i < parameters.Count(); i++)
{
sb.Append("{" + i.ToString() + "} ");
}
string commandstring = sb.ToString();
return _db.ExecuteQuery<T>(commandstring, parameters);
}
It's a little bit brittle in that your parameters must be set up in the proper order, and it's probably offensive to some...but it does accomplish the goal.
You can use this instead:
new SqlParameter { ParameterName = "UserID", Value =txtuserid.Text }
This equivalent in System.Data.SqlClient to :
SqlParameter[] param=new SqlParameter[2];
param[0]=new SqlParameter("#UserID",txtuserid)
Every programmer ends up with a set of utility classes after a while. Some of them are true programming pearls and they are reused in several of your projects. For example, in java:
class Separator {
private String separator;
private boolean called;
public Separator(String aSeparator) {
separator = aSeparator;
called = false;
}
#Override
public String toString() {
if (!called) {
called = true;
return "";
} else {
return separator;
}
}
}
and:
public class JoinHelper {
public static <T> String join(T... elements) {
return joinArray(" ", elements);
}
public static <T> String join(String separator, T... elements) {
return joinArray(separator, elements);
}
private static <T> String joinArray(String sep, T[] elements) {
StringBuilder stringBuilder = new StringBuilder();
Separator separator = new Separator(sep);
for (T element : elements) {
stringBuilder.append(separator).append(element);
}
return stringBuilder.toString();
}
}
What is your most reused class?
System.Object - almost all my types extend it.
A utility class that has logging and email functionality. An extensions class that contains extension methods. A reporting class that basically harness the reporting services web service and makes it easy to stream reports as excel, pdf, etc.
Examples...
1.) Utility Class (static)
public static void LogError(Exception ex)
{
EventLog log = new EventLog();
if (ex != null)
{
log.Source = ConfigurationManager.AppSettings["EventLog"].ToString();
StringBuilder sErrorMessage = new StringBuilder();
if (HttpContext.Current.Request != null && HttpContext.Current.Request.Url != null)
{
sErrorMessage.Append(HttpContext.Current.Request.Url.ToString() + System.Environment.NewLine);
}
sErrorMessage.Append(ex.ToString());
log.WriteEntry(sErrorMessage.ToString(), EventLogEntryType.Error);
}
}
2.) Extensions Class
public static IEnumerable<TSource> WhereIf<TSource>(this IEnumerable<TSource> source, bool condition, Func<TSource, bool> predicate)
{
if (condition)
return source.Where(predicate);
else
return source;
}
public static short getLastDayOfMonth(short givenMonth, short givenYear)
{
short lastDay = 31;
switch (givenMonth)
{
case 4:
case 6:
case 9:
case 11:
lastDay = 30;
break;
case 2:
if ((int)givenYear % 4 == 0)
{
lastDay = 29;
}
else
{
lastDay = 28;
}
break;
}
return lastDay;
}
Most reused but boring:
public static void handleException(Exception e) throws RuntimeException {
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
throw new RuntimeException(e); //NOPMD
}
Less boring (also methods for building lists and sets):
/**
* Builds a Map that is based on the Bean List.
*
* #param items Bean List items
* #param keyField Bean Field that will be key of Map elements (not null)
* #return a Map that is based on the Bean List
*/
#SuppressWarnings("unchecked")
public static <T, K> Map<K, T> buildMapFromCollection(final Collection<T> items,
boolean linkedMap,
final String keyField,
final Class<K> keyType) {
if (items == null) {
return Collections.emptyMap();
}
if (keyField == null) {
throw new IllegalArgumentException("KeyField is null");
}
final Map<K, T> result;
if (linkedMap) {
result = new LinkedHashMap<K, T>();
} else {
result = new HashMap<K, T>();
}
BeanMapper mapper = null;
for (final T item : items) {
if (mapper == null) {
mapper = new BeanMapper(item.getClass());
}
final K key = (K) mapper.getFieldValue(item, keyField);
result.put(key, item);
}
return result;
}
Logger class: Which logs the flow of control in a log file.
Configuration Reader/Setter: which reads the configuration from ini/xml file and sets the environment of the application
Most reused? Hmmm...
boost::shared_ptr<> with boost::weak_ptr<>
probably most reused (also probably most bang-for-buck ratio)
Globals
Just a simple class with static DBConnString, and a few other app wide settings.
Have reused the simple file in about 2 dozen projects since working with .Net
A ConcurrentDictionary I wrote, which I now seem to use everywhere (I write lots of parallel programs)