CheckStyle module prevent "too many" carriage returns? - checkstyle

Is there a CheckStyle module that will mimic the behavior below?
For Java + IntelliJ.
With StyleCop, it will natively check for "too many" carriage returns.
Sample C# code:
Notice the lines BELOW "using System.Collections.Generic" and ABOVE the method "GetSingle" .. they have more-than-one-empty line.
StyleCop would complain, and you would fix by having 1 or 0 empty lines in that space.
I couldn't find anything at : https://checkstyle.sourceforge.io/config_whitespace.html
Or i don't know what the magic word is for what I'm looking for.
namespace Examples.UnitTestingWithInMemoryLoggingExample.SimulatedProject.Bal.Managers
{
using System;
using System.Collections.Generic;
using Examples.UnitTestingWithInMemoryLoggingExample.SimulatedProject.Bal.Managers.Interfaces;
using Examples.UnitTestingWithInMemoryLoggingExample.SimulatedProject.Dal.Interfaces;
using Examples.UnitTestingWithInMemoryLoggingExample.SimulatedProject.Domain;
using Surescripts.Components.Logging.LoggingAbstractBase;
public class EmployeeManager : IEmployeeManager
{
public const string ErrorMessageILoggerFactoryWrapperIsNull = "ILoggerFactoryWrapper is null";
public const string ErrorMessageIEmployeeDataIsNull = "IEmployeeData is null";
public const string LogMsgEmployeeManagerGetAll = "EmployeeManager.GetAll started";
public const string LogMsgEmployeeManagerGetSingle = "EmployeeManager.GetSingle started (key='{0}')";
public const string LogMsgKeyLessThanZero = "Warning Warning Warning. Key less than zero. (key='{0}')";
private readonly ILoggerWrapper<EmployeeManager> logger;
private readonly IEmployeeData empData;
public EmployeeManager(ILoggerFactoryWrapper loggerFactory, IEmployeeData empData)
{
if (null == loggerFactory)
{
throw new ArgumentNullException(ErrorMessageILoggerFactoryWrapperIsNull, (Exception)null);
}
this.logger = loggerFactory.CreateLoggerWrapper<EmployeeManager>();
this.empData = empData ?? throw new ArgumentNullException(ErrorMessageIEmployeeDataIsNull, (Exception)null);
}
public ICollection<Employee> GetAll()
{
this.logger.LogInformation(LogMsgEmployeeManagerGetAll);
ICollection<Employee> returnItems = this.empData.GetAll();
return returnItems;
}
public Employee GetSingle(long key)
{
this.logger.LogInformation(string.Format(LogMsgEmployeeManagerGetSingle, key));
if (key < 0)
{
/* simple example to show IsEnabled */
if (this.logger.IsEnabled(LoggingEventTypeEnum.Warning))
{
this.logger.Log(new LogEntry(LoggingEventTypeEnum.Warning, string.Format(LogMsgKeyLessThanZero, key)));
}
}
Employee returnItem = this.empData.GetSingle(key);
return returnItem;
}
}
}

Found it
<module name="EmptyLineSeparator">
<property name="allowMultipleEmptyLines" value="false"/>
</module>

Related

NHibernate LinqToHqlGenerator for SQL Server 2008 full text index 'Containing' keyword

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();

Remove namespace prefix while JAXB marshalling

I have JAXB objects created from a schema. While marshalling, the xml elements are getting annotated with ns2. I have tried all the options that exist over the net for this problem, but none of them works. I cannot modify my schema or change package-info.java. Please help
After much research and tinkering I have finally managed to achieve a solution to this problem. Please accept my apologies for not posting links to the original references - there are many and I wasn't taking notes - but this one was certainly useful.
My solution uses a filtering XMLStreamWriter which applies an empty namespace context.
public class NoNamesWriter extends DelegatingXMLStreamWriter {
private static final NamespaceContext emptyNamespaceContext = new NamespaceContext() {
#Override
public String getNamespaceURI(String prefix) {
return "";
}
#Override
public String getPrefix(String namespaceURI) {
return "";
}
#Override
public Iterator getPrefixes(String namespaceURI) {
return null;
}
};
public static XMLStreamWriter filter(Writer writer) throws XMLStreamException {
return new NoNamesWriter(XMLOutputFactory.newInstance().createXMLStreamWriter(writer));
}
public NoNamesWriter(XMLStreamWriter writer) {
super(writer);
}
#Override
public NamespaceContext getNamespaceContext() {
return emptyNamespaceContext;
}
}
You can find a DelegatingXMLStreamWriter here.
You can then filter the marshalling xml with:
// Filter the output to remove namespaces.
m.marshal(it, NoNamesWriter.filter(writer));
I am sure there are more efficient mechanisms but I know this one works.
For me, only changing the package-info.java class worked like a charm, exactly as zatziky stated :
package-info.java
#javax.xml.bind.annotation.XmlSchema
(namespace = "http://example.com",
xmlns = {#XmlNs(prefix = "", namespaceURI = "http://example.com")},
elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
package my.package;
import javax.xml.bind.annotation.XmlNs;
You can let the namespaces be written only once. You will need a proxy class of the XMLStreamWriter and a package-info.java. Then you will do in your code:
StringWriter stringWriter = new StringWriter();
XMLStreamWriter writer = new Wrapper((XMLStreamWriter) XMLOutputFactory
.newInstance().createXMLStreamWriter(stringWriter));
JAXBContext jaxbContext = JAXBContext.newInstance(Collection.class);
Marshaller jaxbMarshaller = jaxbContext.createMarshaller();
jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
jaxbMarshaller.marshal(books, writer);
System.out.println(stringWriter.toString());
Proxy class (the important method is "writeNamespace"):
class WrapperXMLStreamWriter implements XMLStreamWriter {
private final XMLStreamWriter writer;
public WrapperXMLStreamWriter(XMLStreamWriter writer) {
this.writer = writer;
}
//keeps track of what namespaces were used so that not to
//write them more than once
private List<String> namespaces = new ArrayList<String>();
public void init(){
namespaces.clear();
}
public void writeStartElement(String localName) throws XMLStreamException {
init();
writer.writeStartElement(localName);
}
public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException {
init();
writer.writeStartElement(namespaceURI, localName);
}
public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException {
init();
writer.writeStartElement(prefix, localName, namespaceURI);
}
public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
if(namespaces.contains(namespaceURI)){
return;
}
namespaces.add(namespaceURI);
writer.writeNamespace(prefix, namespaceURI);
}
// .. other delegation method, always the same pattern: writer.method() ...
}
package-info.java:
#XmlSchema(elementFormDefault=XmlNsForm.QUALIFIED, attributeFormDefault=XmlNsForm.UNQUALIFIED ,
xmlns = {
#XmlNs(namespaceURI = "http://www.w3.org/2001/XMLSchema-instance", prefix = "xsi")})
package your.package;
import javax.xml.bind.annotation.XmlNs;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
You can use the NamespacePrefixMapper extension to control the namespace prefixes for your use case. The same extension is supported by both the JAXB reference implementation and EclipseLink JAXB (MOXy).
http://wiki.eclipse.org/EclipseLink/Release/2.4.0/JAXB_RI_Extensions/Namespace_Prefix_Mapper
Every solution requires complex overwriting or annotations which seems not to work with recent version. I use a simpler approach, just by replacing the annoying namespaces. I wish Google & Co would use JSON and get rid of XML.
kml.marshal(file);
String kmlContent = FileUtils.readFileToString(file, "UTF-8");
kmlContent = kmlContent.replaceAll("ns2:","").replace("<kml xmlns:ns2=\"http://www.opengis.net/kml/2.2\" xmlns:ns3=\"http://www.w3.org/2005/Atom\" xmlns:ns4=\"urn:oasis:names:tc:ciq:xsdschema:xAL:2.0\" xmlns:ns5=\"http://www.google.com/kml/ext/2.2\">", "<kml>");
FileUtils.write(file, kmlContent, "UTF-8");

How to prevent Gson serialize / deserialize the first character of a field (underscore)?

My class:
class ExampleBean {
private String _firstField;
private String _secondField;
// respective getters and setters
}
I want to appear as follows:
{
"FirstField":"value",
"SecondField":"value"
}
And not like this
{
"_FirstField":"value",
"_SecondField":"value"
}
I initialize the parser as follows:
GsonBuilder builder = new GsonBuilder();
builder.setDateFormat(DateFormat.LONG);
builder.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE);
builder.setPrettyPrinting();
set_defaultParser(builder.create());
I could see the API and in the documentation of "FieldNamePolicy" but I am surprised that not give the option to skip "_"
I also know I can use the annotation...
# SerializedName (" custom_naming ")
...but do not want to have to write this for alllllll my fields ...
It's very useful for me to distinguish between local variables and fields of a class. :( Any Idea?
EDIT: There would be many obvious solutions, (inheritance, gson overwriting methods, regular expresions). My question is more focused on whether there is a native solution of gson or a less intrusive fix?
Maybe we could propose as new FieldNamePolicy?
GsonBuilder provides a method setFieldNamingStrategy() that allows you to pass your own FieldNamingStrategy implementation.
Note that this replaces the call to setFieldNamingPolicy() - if you look at the source for GsonBuilder these two methods are mutually exclusive as they set the same internal field (The FieldNamingPolicy enum is a FieldNamingStrategy).
public class App
{
public static void main(String[] args)
{
Gson gson = new GsonBuilder()
.setFieldNamingStrategy(new MyFieldNamingStrategy())
.setPrettyPrinting()
.create();
System.out.println(gson.toJson(new ExampleBean()));
}
}
class ExampleBean
{
private String _firstField = "first field value";
private String _secondField = "second field value";
// respective getters and setters
}
class MyFieldNamingStrategy implements FieldNamingStrategy
{
public String translateName(Field field)
{
String fieldName =
FieldNamingPolicy.UPPER_CAMEL_CASE.translateName(field);
if (fieldName.startsWith("_"))
{
fieldName = fieldName.substring(1);
}
return fieldName;
}
}
Output:
{
"FirstField": "first field value",
"SecondField": "second field value"
}
What you want is
import java.lang.reflect.Field;
import java.text.DateFormat;
import com.google.gson.FieldNamingStrategy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class GsonExample {
public static void main(String... args) throws Exception {
final GsonBuilder builder = new GsonBuilder();
builder.setDateFormat(DateFormat.LONG);
builder.setPrettyPrinting();
builder.setFieldNamingStrategy(new FieldNamingStrategy() {
#Override
public String translateName(Field f) {
String fieldName = f.getName();
if(fieldName.startsWith("_") && fieldName.length() > 1) {
fieldName = fieldName.substring(1, 2).toUpperCase() + fieldName.substring(2);
}
return fieldName;
}
});
final Gson gson = builder.create();
System.out.println(gson.toJson(new ExampleBean("example", "bean")));
}
private static class ExampleBean {
private final String _firstField;
private final String _secondField;
private ExampleBean(String _firstField, String _secondField) {
this._firstField = _firstField;
this._secondField = _secondField;
}
}
}
which generates
{"FirstField":"example","SecondField":"bean"}

WcfFacility and Sequence contains no elements error?

I have wcf library with service contracts and implementations.
[ServiceContract]
public interface IServiceProtoType
{
[OperationContract]
Response GetMessage(Request request);
[OperationContract]
String SayHello();
}
[DataContract]
public class Request
{
private string name;
[DataMember]
public string Name
{
get { return name; }
set { name = value; }
}
}
[DataContract]
public class Response
{
private string message;
[DataMember]
public string Message
{
get { return message; }
set { message = value; }
}
}
public class MyDemoService : IServiceProtoType
{
public Response GetMessage(Request request)
{
var response = new Response();
if (null == request)
{
response.Message = "Error!";
}
else
{
response.Message = "Hello, " + request.Name;
}
return response;
}
public string SayHello()
{
return "Hello, World!";
}
}
I have windows service project that references this library, where MyService is just an empty shell that inherits ServiceBase. This service is installed and running under local system.
static void Main()
{
ServiceBase.Run(CreateContainer().Resolve());
}
private static IWindsorContainer CreateContainer()
{
IWindsorContainer container = new WindsorContainer();
container.Install(FromAssembly.This());
return container;
}
public class ServiceInstaller : IWindsorInstaller
{
#region IWindsorInstaller Members
public void Install(IWindsorContainer container, Castle.MicroKernel.SubSystems.Configuration.IConfigurationStore store)
{
string myDir;
if (string.IsNullOrEmpty(AppDomain.CurrentDomain.RelativeSearchPath))
{
myDir = AppDomain.CurrentDomain.BaseDirectory;
}
else
{
myDir = AppDomain.CurrentDomain.RelativeSearchPath;
}
var wcfLibPath = Path.Combine(myDir , "WcfDemo.dll");
string baseUrl = "http://localhost:8731/DemoService/{0}";
AssemblyName myAssembly = AssemblyName.GetAssemblyName(wcfLibPath);
container
.Register(
AllTypes
.FromAssemblyNamed(myAssembly.Name)
.InSameNamespaceAs<WcfDemo.MyDemoService>()
.WithServiceDefaultInterfaces()
.Configure(c =>
c.Named(c.Implementation.Name)
.AsWcfService(
new DefaultServiceModel()
.AddEndpoints(WcfEndpoint
.BoundTo(new WSHttpBinding())
.At(string.Format(baseUrl,
c.Implementation.Name)
)))), Component.For<ServiceBase>().ImplementedBy<MyService>());
}
#endregion
}
In Client Console app I have the following code and I am getting the following error:
{"Sequence contains no elements"}
static void Main(string[] args)
{
IWindsorContainer container = new WindsorContainer();
string baseUrl = "http://localhost:8731/DemoService/{0}";
container.AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero);
container
.Register(
Types
.FromAssemblyContaining<IServiceProtoType>()
.InSameNamespaceAs<IServiceProtoType>()
.Configure(
c => c.Named(c.Implementation.Name)
.AsWcfClient(new DefaultClientModel
{
Endpoint = WcfEndpoint
.BoundTo(new WSHttpBinding())
.At(string.Format(baseUrl,
c.Name.Substring(1)))
})));
var service1 = container.Resolve<IServiceProtoType>();
Console.WriteLine(service1.SayHello());
Console.ReadLine();
}
I have an idea what this may be but you can stop reading this now (and I apologize for wasting your time in advance) if the answer to the following is no:
Is one (or more) of Request, Response, or MyDemoService in the same namespace as IServiceProtoType?
I suspect that Windsor is getting confused about those, since you are doing...
Types
.FromAssemblyContaining<IServiceProtoType>()
.InSameNamespaceAs<IServiceProtoType>()
... and then configuring everything which that returns as a WCF client proxy. This means that it will be trying to create proxies for things that should not be and hence a Sequence Contains no Elements exception (not the most useful message IMHO but crushing on).
The simple fix would be just to put your IServiceProtoType into its own namespace (I often have a namespace like XXXX.Services for my service contracts).
If that is not acceptable to you then you need to work out another way to identify just the service contracts - take a look at the If method for example or just a good ol' Component.For perhaps.

Trouble Passing Parameter to LinqToSql Stored Procedure

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)