Dapper Extension Ms Access System.Data.OleDb.OleDbException - ms-access

I just started to use Dapper. Dapper works fine. As a next step when I tried to integrate with Dapper Extension. It generates an exception called System.Data.OleDb.OleDbException "Additional information: Characters found after end of SQL statement." Why is that? Dapper Extension doesn't support Ms Access (because of the end character) or problem with my code or I am missing something. My code is below
using (var conn = new OleDbConnection(#"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=myAccessFile.accdb;"))
{
conn.Open();
conn.Insert<Person>(new Person { Name = "John Stan", Age = 20 });
}

According to an MSDN article,
Some database engines, such as the Microsoft Access Jet database engine, do not support output parameters and cannot process multiple statements in a single batch.
So the problem is that the Insert method is generating a statement such as
INSERT INTO [Person] ([Person].[PersonName]) VALUES (#PersonName);
SELECT CAST(SCOPE_IDENTITY() AS BIGINT) AS [Id]
and Access can't deal with it.
Reading around, it seems like that are various suggestions as to how to do insert-and-get-new-record-key when dealing with Access (that MSDN article suggests a second SELECT statement) but that doesn't help if you're using the DapperExtensions library, since that is what generates the query for you.
So, basically, I think that you are correct in thinking that DapperExtensions won't work with Access.
On a side note, I had a nightmare trying to find out what queries were being generated. There are various articles that talk about a registry hack to set a "JETSHOWPLAN" value to "ON" but I couldn't make any of them work. In the end, I created wrapped database connection and command classes so that the queries could be captured on the way out. In case this is of any use to anyone in the future, I'm including it below..
The database connection initialisation code needs to change slightly - eg.
var connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Database2.mdb;";
using (var conn = new WrappedDbConnection(new OleDbConnection(connectionString)))
{
conn.Insert<Person>(new Person { PersonName = "Dan" });
}
and the following two classes need to be defined -
public class WrappedDbConnection : IDbConnection
{
private readonly IDbConnection _conn;
public WrappedDbConnection(IDbConnection connection)
{
if (connection == null)
throw new ArgumentNullException(nameof(connection));
_conn = connection;
}
public string ConnectionString
{
get { return _conn.ConnectionString; }
set { _conn.ConnectionString = value; }
}
public int ConnectionTimeout
{
get { return _conn.ConnectionTimeout; }
}
public string Database
{
get { return _conn.Database; }
}
public ConnectionState State
{
get { return _conn.State; }
}
public IDbTransaction BeginTransaction()
{
return _conn.BeginTransaction();
}
public IDbTransaction BeginTransaction(IsolationLevel il)
{
return _conn.BeginTransaction(il);
}
public void ChangeDatabase(string databaseName)
{
_conn.ChangeDatabase(databaseName);
}
public void Close()
{
_conn.Close();
}
public IDbCommand CreateCommand()
{
return new WrappedDbCommand(_conn.CreateCommand());
}
public void Dispose()
{
_conn.Dispose();
}
public void Open()
{
_conn.Open();
}
}
public class WrappedDbCommand : IDbCommand
{
private readonly IDbCommand _cmd;
public WrappedDbCommand(IDbCommand command)
{
if (command == null)
throw new ArgumentNullException(nameof(command));
_cmd = command;
}
public string CommandText
{
get { return _cmd.CommandText; }
set { _cmd.CommandText = value; }
}
public int CommandTimeout
{
get { return _cmd.CommandTimeout; }
set { _cmd.CommandTimeout = value; }
}
public CommandType CommandType
{
get { return _cmd.CommandType; }
set { _cmd.CommandType = value; }
}
public IDbConnection Connection
{
get { return _cmd.Connection; }
set { _cmd.Connection = value; }
}
public IDataParameterCollection Parameters
{
get { return _cmd.Parameters; }
}
public IDbTransaction Transaction
{
get { return _cmd.Transaction; }
set { _cmd.Transaction = value; }
}
public UpdateRowSource UpdatedRowSource
{
get { return _cmd.UpdatedRowSource; }
set { _cmd.UpdatedRowSource = value; }
}
public void Cancel()
{
_cmd.Cancel();
}
public IDbDataParameter CreateParameter()
{
return _cmd.CreateParameter();
}
public void Dispose()
{
_cmd.Dispose();
}
public int ExecuteNonQuery()
{
Console.WriteLine($"[ExecuteNonQuery] {_cmd.CommandText}");
return _cmd.ExecuteNonQuery();
}
public IDataReader ExecuteReader()
{
Console.WriteLine($"[ExecuteReader] {_cmd.CommandText}");
return _cmd.ExecuteReader();
}
public IDataReader ExecuteReader(CommandBehavior behavior)
{
Console.WriteLine($"[ExecuteReader({behavior})] {_cmd.CommandText}");
return _cmd.ExecuteReader();
}
public object ExecuteScalar()
{
Console.WriteLine($"[ExecuteScalar] {_cmd.CommandText}");
return _cmd.ExecuteScalar();
}
public void Prepare()
{
_cmd.Prepare();
}
}
Now, the queries are written to the console before being sent to the database.

Related

mybatis clientGenerated couldn't call back

i code a plugin for mybatis generator, but in clientGenerated of extends plugin method doesn't work.
please helpe me ~ ^_^
code is in under:
public class MapperAnnotationPlugin extends PluginAdapter {
private final static Map<String, String> ANNOTATION_IMPORTS;
static {
ANNOTATION_IMPORTS = new HashMap<>();
ANNOTATION_IMPORTS.put("#Mapper", "org.apache.ibatis.annotations.Mapper");
ANNOTATION_IMPORTS.put("#Repository", "org.springframework.stereotype.Repository");
}
private List<String> annotationList;
#Override
public void initialized(IntrospectedTable introspectedTable) {
super.initialized(introspectedTable);
this.annotationList = new ArrayList<>();
Properties properties = this.getProperties();
boolean findMapper = false;
for (Object key : properties.keySet()) {
String keyStr = key.toString().trim();
if (keyStr.startsWith("#Mapper")) {
findMapper = true;
}
if (StringUtility.isTrue(properties.getProperty(key.toString()))) {
annotationList.add(keyStr);
}
}
if (!findMapper) {
annotationList.add(0, "#Mapper");
}
}
#Override
public boolean clientGenerated(Interface interfaze, IntrospectedTable introspectedTable) {
super.clientGenerated(interfaze, introspectedTable);
for (String annotation : annotationList) {
if ("#Mapper".equals(annotation)) {
if (introspectedTable.getTargetRuntime() == IntrospectedTable.TargetRuntime.MYBATIS3) {
interfaze.addImportedType(new FullyQualifiedJavaType(ANNOTATION_IMPORTS.get(annotation)));
interfaze.addAnnotation(annotation);
}
} else if (Objects.nonNull(ANNOTATION_IMPORTS.get(annotation))) {
logger.info(PluginConst.TEACHEE_PLUGIN + "添加" + annotation);
interfaze.addImportedType(new FullyQualifiedJavaType(ANNOTATION_IMPORTS.get(annotation)));
interfaze.addAnnotation(annotation);
}
}
return true;
}
}
in second method, in debug, it had not go this method, so what could i do in next step
Same problem when I maked a plugin for mybatis-generator-plugin. The method of clientGenerated didnot be callback. It is my way, call from another method which include Interface object.
#Override
public boolean clientCountByExampleMethodGenerated(Method method, Interface interfaze, IntrospectedTable introspectedTable) {
this.clientGenerated(interfaze, null, introspectedTable);
return false;
}
Both generator-core/generator-plugin version is 1.4.0, work fine now.
https://github.com/mybatis/generator/releases/tag/mybatis-generator-1.4.0

How to mock a Consumer argument using EasyMock with PowerMock

I have a test scenario where I need to mock a Consumer parameter.
In the following code the startTracer is the method to be tested.
class TracerService {
private TracerController tracerController;
public void startTracer(String tracerName, Object param1) {
if (attendStartConditions(tracerName, param1)) {
executeOnTracerControllerScope(tracerController -> tracerController.startTracer(param1));
}
}
...
}
Basically, I want to test if the tracerController.startTracer(param1) is receiving the param1 as argument.
Capture<Object> method1Param1 = newCapture();
tracerController.startTracer(capture(method1Param1));
expectLastCall().once();
...
tracerService.startTracer("TEST", "value1");
assertThat(method1Param1.getValue()).isEqualsTo("value1");
How I can configure EasyMock/PowerMock for that executeOnTracerControllerScope execute tracerController.startTracer without invocating their internal code?
tracerController is a mock. So startTracer won't be called on it. As defined right now, it will simply do nothing. The code doing what you are asking should be something like that:
Capture<Object> method1Param1 = newCapture();
tracerController.startTracer(capture(method1Param1)); // no need for the expect, it's the default
replay(tracerController);
// ...
tracerService.startTracer("TEST", "value1");
assertThat(method1Param1.getValue()).isEqualsTo("value1");
Of course, attendStartConditions and executeOnTracerControllerScope will be called for real.
Following your comment, if you want to mock executeOnTracerControllerScope, you will do the code below. However, your lambda won't be called anymore. So you won't be able to validate the param.
public class MyTest {
#Test
public void test() {
TracerController tracerController = mock(TracerController.class);
TracerService service = partialMockBuilder(TracerService.class)
.withConstructor(tracerController)
.addMockedMethod("executeOnTracerControllerScope")
.mock();
replay(tracerController);
service.startTracer("tracer", "param");
}
}
class TracerService {
private final TracerController tracerController;
public TracerService(TracerController tracerController) {
this.tracerController = tracerController;
}
public boolean attendStartConditions(String tracerName, Object param1) {
return true;
}
public void executeOnTracerControllerScope(Consumer<TracerController> tracer) {
tracer.accept(tracerController);
}
public void startTracer(String tracerName, Object param1) {
if (attendStartConditions(tracerName, param1)) {
executeOnTracerControllerScope(tracerController -> tracerController.startTracer(param1));
}
}
}
interface TracerController {
void startTracer(Object param1);
}

Why is this <p:selectManyMenu> not working? (getAllDatasourceGroups() is not even called once)

My problem is about this primefaces tag:
<p:selectManyCheckbox id="datasourceGroup" value="#{sessionBean.datasourceGroups}" converter="datasourceGroupConverter">
<f:selectItems value="#{sesionBean.getAllDatasourceGroups()}" var="group" itemLabel="#{group.toString()}" itemValue="#{group}" />
</p:selectManyCheckbox>
It does not render any visible output (checkboxes) at all. From logging output i know that the 'sessionBean.getAllDatasourceGroups()' method is not even called once during page refresh. only the 'sessionBean.getDatasourcegroups()' getter for the 'datasourceGroups' property is called once.
And i can't figure out what the problem is. I have very similar usecases of <p:selectManyMenu> and <p:selectOneMenu> on the same page and they work fine. So i have a basic understanding of how this works...or so i thought :-)
here are the other relevant parts of the code for reference:
SessionBean:
#ManagedBean
#SessionScoped
public class SessionBean implements Serializable {
private List<DatasourceGroup> datasourceGroups = new ArrayList<>();
public List<DatasourceGroup> getDatasourceGroups() {
return datasourceGroups;
}
public void setDatasourceGroups(List<DatasourceGroup> datasourceGroups) {
this.datasourceGroups = datasourceGroups;
}
public List<DatasourceGroup> getAllDatasourceGroups() {
List<DatasourceGroup> list = Arrays.asList(DatasourceGroup.values());
return list;
}
}
DatasourceGroup Enum:
public enum DatasourceGroup {
KUNDEN (Permission.ZugriffKunden),
INKASSO (Permission.ZugriffInkasso),
INTERESSENTEN (Permission.ZugriffInteressenten),
WARN (Permission.ZugriffWarnadressen);
private Permission permissionNeeded;
DatasourceGroup(Permission permission) {
this.permissionNeeded=permission;
}
public Permission getPermissionNeeded() {
return permissionNeeded;
}
}
And the DatasourceGroupConverter:
#FacesConverter("datasourceGroupConverter")
public class DatasourceGroupConverter implements Converter {
#Override
public Object getAsObject(FacesContext fc, UIComponent uic, String value) {
if (Toolbox.isNullOrEmpty(value))
return null;
try {
return DatasourceGroup.valueOf(value);
} catch (IllegalArgumentException e) {
throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Conversion Error:",
"'" + value + "' is not a valid datasource group name"));
}
}
#Override
public String getAsString(FacesContext fc, UIComponent uic, Object object) {
if(object != null && object instanceof DatasourceGroup) {
return ((DatasourceGroup)object).toString();
}
return null;
}
}
I'm using primefaces 6.0 by the way.

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.

linq2sql missing event model?

How come the "Table" classes Generated in the Dbml do not contain useful events like
OnBeforeInsert
OnBeforeUpdate
OnAfterInsert
etc.
Am I missing something?
This question is related to frustration trying to set timestamp columns.
UPDATE
I created the following method of doing this neatly what does everyone think?
public class Model
{
internal virtual void OnBeforeInsert()
{
}
internal virtual void OnBeforeUpdate()
{
}
}
public partial class DbDataContext
{
public override void SubmitChanges(System.Data.Linq.ConflictMode failureMode)
{
foreach (var insert in this.GetChangeSet().Inserts)
{
if (insert is Model)
{
((Model)insert).OnBeforeInsert();
}
}
foreach (var update in this.GetChangeSet().Updates)
{
if (update is Model)
{
((Model)update).OnBeforeUpdate();
}
}
base.SubmitChanges(failureMode);
}
}
public partial class Address : Model
{
internal override void OnBeforeInsert()
{
var created = DateTime.Now;
this._Modified = created;
this._Created = created;
}
}
I had a similar issue like this recently.
There is a partial method in the generated class for "OnValidate". Simply declaring the method in your partial will force it to be called (vb.net does not support partial methods like c#) or in c# simply declare a partial method.
The method is passed a System.Data.Linq.ChangeAction enum that is either: Delete, Insert, Update, or None.
Below is a sample of what you did using the built in partial method.
public partial class Address
{
private partial void OnValidate(System.Data.Linq.ChangeAction action)
{
if (action == System.Data.Linq.ChangeAction.Insert)
{
var created = DateTime.Now;
this._Modified = created;
this._Created = created;
} else if (action == System.Data.Linq.ChangeAction.Update) {
this._Modified = DateTime.Now;
}
}
}