Not Implemented Exception while using Insight.Database micro ORM - micro-orm

I was trying to use the cool Insight.Database micro ORM and run into a Not Implemeneted exception everytime I try to invoke the InsertCustomer method in the CustomerRepository.Any help would be appreciated
Update: I made sure that the method name matches the sql server stored procedure name
public class CustomerRepository
{
private ICustomerRepository _repo;
public static async Task<int> InsertCustomer(Customer cust)
{
var _repo = ConfigSettings.CustomerRepository;
return await _repo.InsertCustomer(cust);
}
}
public class ConfigSettings
{
private static ICustomerRepository _customerRepository;
public static ICustomerRepository CustomerRepository
{
get
{
if (_customerRepository == null)
{
_customerRepository = new SqlConnection(ConfigurationManager.ConnectionStrings["CustomerService_Conn_String"].ConnectionString).AsParallel<ICustomerRepository>();
}
return _customerRepository;
}
}
}
[Sql(Schema="dbo")]
public interface ICustomerRepository
{
[Sql("dbo.InsertCustomer")]
Task<int> InsertCustomer(Customer cust);
}

If you're getting a NotImplementedException, and running v4.1.0 to 4.1.3 you're probably running into a problem registering your database provider.
I recommend using v4.1.4 or later and making sure you register the provider for your database.
See
https://github.com/jonwagner/Insight.Database/wiki/Installing-Insight
If you have any more problems, you can post an issue on github.

Related

Spring boot multithreaded async not working

The task is to call a database, retrieve certain records update and save them.
As the amount of records if fairly large we want to do this Async, however, this doesn't seem to be implemented correctly.
The main class:
#SpringBootApplication
#EnableAsync
MainApplication() {
#Bean("threadPoolExecutor")
public TaskExecutor getAsyncExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(DataSourceConfig.getTHREAD_POOL_SIZE());
executor.setMaxPoolSize(DataSourceConfig.getTHREAD_POOL_SIZE());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setThreadNamePrefix("RetryEnhancement-");
return executor;
}
}
Method in the first service:
#Service
public class FirstService() {
#Transactional
public void fullProcess() {
for(int counter = 0; counter < ConfigFile.getTHREADS(); counter++){
secondaryService.threads();
}
}
}
Method in the second service:
#Service
public class SecondService () {
#Async("threadPoolExecutor")
public void threads() {
while(thirdService.threadMethod()) {
//doNothing
}
}
}
Method in the third service:
#Service
public class ThirdService() {
#Transactional
public boolean threads() {
Record record = repository.fetchRecord();
if(record!=null) {
updateRecord(record);
saveRecord(record);
return true;
} else {
return false;
}
}
}
Repository:
public interface repository extends CrudRepository<Record, long> {
#Lock(LockModeType.PESSIMISTIC_WRITE)
Record fetchRecord();
}
The issue I'm finding is that, while the code executes perfectly fine, it seems to have a Synchronous execution (found by adding a .sleep and watching the execution in the logger).
The seperate threads seem to be waiting until the other is executed.
I'm probably doing something wrong and if another thread already explains the issue, than please refer it, though I have not been able to find this issue in a different thread.
Your solution is way to complex. Ditch all of that and just inject the TaskExecutor and do the updateRecord in a separate thread (you might need to retrieve it again as you are now using a different thread and thus connection.
Something like this should do the trick
private final TaskExecutor executor; // injected through constructor
public void process() {
Stream<Record> records = repository.fetchRecords(); // Using a stream gives you a lazy cursor!
records.forEach(this::processRecord);
}
private void processRecord(Record record) {
executor.submit({
updateRecord(record);
saveRecord(record);
});
}
You might want to put the processRecord into another object and make it #Transactional or wrap it in a TransactionTemplate to get that behavior.

How to ensure our business-service is using the same db connection as the servicestack-service

We do have a few business services, which require an IDBConnection.
It's quite important that these services do use the same dbconnection as the 'normal' Service-Stack service, so we do have atomic transactions.
our current solution for this problem is, to instantiate the business service in the servicestack-service constructor (using the IDbConnection that servicestack provides)
private readonly ITaskService _taskService;
public RegistrationService(IEmailService emailService, ITextProvider textProvider)
{
this._taskService = new TaskService(Db);
}
However, I feel like this is not very 'smart' and there might be a way better solution which I'm overlooking right now.
Would a better option be, to inject the DbFactory instead of the plain connection? If so, does DbFactory already solve this problem?
Best,
Daniel
If you need to use the same open Db connection as that of a ServiceStack Service you should pass it in from your Service, e.g:
public class MyServices : Service
{
public IMyDep MyDep { get; set; }
public object Any(MyRequest request)
{
MyDep.Method(Db);
}
}
Alternatively you can override GetDbConnection() in your AppHost to have it return the same db connection for that request, e.g:
public override IDbConnection GetDbConnection(IRequest req = null)
{
if (req != null)
{
if (req.Items.TryGetValue("RequestDb", out var oDb) && oDb is IDbConnection db)
return db;
db = base.GetDbConnection(req);
req.Items["RequestDb"] = db;
return db;
}
return base.GetDbConnection(req);
}
That in your dependencies can access from AppHost.GetDbConnection(), e.g:
public class MyDep : IMyDep
{
private IDbConnection db;
public virtual IDbConnection Db => db ?? (db = HostContext.AppHost.GetDbConnection(Request));
public object Method()
{
var row = Db.Select<Table>();
}
}

How to write client proxy for SPI and what the difference between client and server proxies?

I have developed own idGenerator based on Hazelcast IdGenerator class (with storing each last_used_id into db). Now I want to run hazelcast cluster as a single java application and my web-application as other app (web-application restart shouldn't move id values to next block). I move MyIdGeneratorProxy and MyIdGeneratorService to new application, run it, run web-application as a hazelcast-client and get
IllegalArgumentException: No factory registered for service: ecs:impl:idGeneratorService
It was okay when client and server were the same application.
It seems it's unable to process without some clientProxy. I have compared IdGeneratorProxy and ClientIdGeneratorProxy and it looks the same. What is the idea? How to write client proxy for services? I have found no documentation yet. Is direction of investigations correct? I thought it is possible to divide hazelcast inner services (like a id generator service) and my business-processes. Should I store custom ClientProxy (for custom spi) in my web-application?
This is a demo how to create a client proxy, the missing part CustomClientProxy function call, is quit complicated(more like a server proxy,here is called ReadRequest, the server is called Operation), you can find a how AtomicLong implement.For every client proxy method you have to make a request.
#Test
public void client() throws InterruptedException, IOException
{
ClientConfig cfg = new XmlClientConfigBuilder("hazelcast-client.xml").build();
ServiceConfig serviceConfig = new ServiceConfig();
serviceConfig.setName(ConnectorService.NAME)
.setClassName(ConnectorService.class.getCanonicalName())
.setEnabled(true);
ProxyFactoryConfig proxyFactoryConfig = new ProxyFactoryConfig();
proxyFactoryConfig.setService(ConnectorService.NAME);
proxyFactoryConfig.setClassName(CustomProxyFactory.class.getName());
cfg.addProxyFactoryConfig(proxyFactoryConfig);
HazelcastInstance hz = HazelcastClient.newHazelcastClient(cfg);
Thread.sleep(1000);
for (int i = 0; i < 10; i++)
{
Connector c = hz.getDistributedObject(ConnectorService.NAME, "Connector:" + ThreadLocalRandom.current()
.nextInt(10000));
System.out.println(c.snapshot());
}
}
private static class CustomProxyFactory implements ClientProxyFactory
{
#Override
public ClientProxy create(String id)
{
return new CustomClientProxy(ConnectorService.NAME, id);
}
}
private static class CustomClientProxy extends ClientProxy implements Connector
{
protected CustomClientProxy(String serviceName, String objectName)
{
super(serviceName, objectName);
}
#Override
public ConnectorState snapshot()
{
return null;
}
#Override
public void loadState(ConnectorState state)
{
}
#Override
public boolean reconnect(HostNode node)
{
return false;
}
#Override
public boolean connect()
{
return false;
}
}
EDIT
In hazelcast the IdGenerate is implemented as a wrapper for AtomicLong, you should implement you IdGenerate by you own, instead of extend IdGenerate.
So you have to implement these(more like a todo list XD):
API
interface MyIdGenerate
Server
MyIdGenerateService
MyIdGenerateProxy
MyIdGenerateXXXOperation
Client
ClientMyIdGenerateFactory
ClientMyIdGenerateProxy
MyIdGenerateXXXRequest
I also made a sequence(same as IdGenerate) here, this is backed by zookeeper or redis,also it's easy to add a db backend,too.I will integrate to hazelcast if I got time.

How can I instantiate OWIN IDataProtectionProvider in Azure Web Jobs?

I need an instance of IDataProtectionProvider to generate email confirmation tokens using the Identity Framework UserManager in an Azure Web Jobs worker:
var confirmToken = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
This crashes because a null IUserTokenProvider<User, int> was passed to the UserManager<User, int> upon constuction.
In the MVC application an instance is created like this:
public class OWINStartup
{
public void Configuration(IAppBuilder app)
{
var dataProtectionProvider = app.GetDataProtectionProvider();
But of course, Azure Web Jobs doesn't have an OWINStartup hook. Any advice?
Taking a look at the Katana source code for the OWIN startup context you can see the default implementation of the DataProtectionProvider is a MachineKeyDataProtectionProvider. Unfortunately this class is not exposed to us, only the DpapiDataProtectionProvider which will not work when hosted in azure.
You can find the implementation of the MachineKeyDataProtectionProvider here. You will need to also implement your own MachineKeyDataProtector as seen here. These are not difficult implmentations and are essentially wrappers around MachineKey.Protect() and MachineKey.Unprotect().
The implementation for MachineKeyDataProtectionProvider and MachineKeyDataProtector from the Katana project source (apache 2.0 license):
internal class MachineKeyProtectionProvider : IDataProtectionProvider
{
public IDataProtector Create(params string[] purposes)
{
return new MachineKeyDataProtector(purposes);
}
}
internal class MachineKeyDataProtector : IDataProtector
{
private readonly string[] _purposes;
public MachineKeyDataProtector(string[] purposes)
{
_purposes = purposes;
}
public byte[] Protect(byte[] userData)
{
return MachineKey.Protect(userData, _purposes);
}
public byte[] Unprotect(byte[] protectedData)
{
return MachineKey.Unprotect(protectedData, _purposes);
}
}
Once you have that implemented it is easy to plug into the UserManager:
var usermanager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>());
var machineKeyProtectionProvider = new MachineKeyProtectionProvider();
usermanager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(machineKeyProtectionProvider.Create("ASP.NET Identity"));
Hope that helps get you in the right direction.

Specific TableController name not working

I have an extremely odd error and wondered if anyone knew the reason for this.
When I create a new DataObject and TableController called Content and ContentController respectively, it doesn't register the tablecontroller and the help documentation it automatically generates has lost its styling.
I can't connect to the controller at all but all other controllers work as expected.
If I just rename it to DataController and that's just the name of the controller, not the dataobject everything works perfectly.
Is ContentController a reserved word of some kind or is this just specifically happening on my machine?
public class DataController : TableController<Content>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
MobileContext context = new MobileContext();
DomainManager = new EntityDomainManager<Content>(context, Request, Services);
}
// GET tables/Content
public IQueryable<Content> GetAllContent()
{
return Query();
}
// GET tables/Content/48D68C86-6EA6-4C25-AA33-223FC9A27959
public SingleResult<Content> GetContent(string id)
{
return Lookup(id);
}
// PATCH tables/Content/48D68C86-6EA6-4C25-AA33-223FC9A27959
public Task<Content> PatchContent(string id, Delta<Content> patch)
{
return UpdateAsync(id, patch);
}
// POST tables/Content/48D68C86-6EA6-4C25-AA33-223FC9A27959
public async Task<IHttpActionResult> PostContent(Content item)
{
Content current = await InsertAsync(item);
return CreatedAtRoute("Tables", new { id = current.Id }, current);
}
// DELETE tables/Content/48D68C86-6EA6-4C25-AA33-223FC9A27959
public Task DeleteContent(string id)
{
return DeleteAsync(id);
}
}
An MVC project will create an application directory called Content. This will override your route mapping to the ContentController.
You can get around this if desired through changing RouteMaps and other trickery although probably the simpliest answer is to change the name of the controller...

Resources