Database path cannot be converted in SQLiteAsyncConnection - c#

I'm learning how to create a local database on mobile devices by using SQLite.Net.Async. I'm following a tutorial step by step but something wrong with my database path. The error message says 'Argument 1 cannot convert from string to System.Func SQLite.Net.SQLiteConnectionWithLock'. I was confused because this code works well on the tutorial sample.
This is my code:
using SQLite.Net.Async;
namespace ToDoList
{
public class TodoItemDatabase
{
readonly SQLiteAsyncConnection asyncdatabase;
public TodoItemDatabase (string dbPath)
{
asyncdatabase = new SQLiteAsyncConnection(dbPath);
//I haven't done further because I was stucked by dbPath error
}
}
}
The sample code works well:
using System.Collections.Generic;
using System.Threading.Tasks;
using SQLite;
namespace Todo
{
public class TodoItemDatabase
{
readonly SQLiteAsyncConnection database;
public TodoItemDatabase(string dbPath)
{
database = new SQLiteAsyncConnection(dbPath);
database.CreateTableAsync<TodoItem>().Wait();
}
public Task<List<TodoItem>> GetItemsAsync()
{
return database.Table<TodoItem>().ToListAsync();
}
public Task<List<TodoItem>> GetItemsNotDoneAsync()
{
return database.QueryAsync<TodoItem>("SELECT * FROM [TodoItem] WHERE [Done] = 0");
}
public Task<TodoItem> GetItemAsync(int id)
{
return database.Table<TodoItem>().Where(i => i.ID == id).FirstOrDefaultAsync();
}
public Task<int> SaveItemAsync(TodoItem item)
{
if (item.ID != 0)
{
return database.UpdateAsync(item);
}
else {
return database.InsertAsync(item);
}
}
public Task<int> DeleteItemAsync(TodoItem item)
{
return database.DeleteAsync(item);
}
}
}

This is the package which is been used in the sample application sqlite-net-pcl

Related

MongoDb C# Driver Projection after GroupBy with generic type

I've spotted an issue while working with mongodb c# driver (v 2.11.1)
I need to perform GroupBy and after select first id from each group.
When working on concrete IMongoQueryable it is working fine.
However when I wrapped it with some Generic helper class I got exception with unsupported method message.
here is code of dotnet core console application which shows the error. It looks like Select after groupby is not implemented for generic only for concrete.
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using System;
using System.Linq;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var sut = new Test<Quote>();
var workingTest1 = sut.QueryableCollection.GroupBy(x => x._id).Select(x => x.First()._id).ToString();
var workingTest2 = sut.TestCallWithCasting();
var notWorkingTest = sut.TestCallWithoutCasting();
}
}
public class Test<TEntity> where TEntity : IMongoDbEntity
{
private IMongoCollection<TEntity> _collection;
public IMongoQueryable<TEntity> QueryableCollection => _collection.AsQueryable();
public Test()
{
var client = new MongoClient();
var database = client.GetDatabase("Quote");
_collection = database.GetCollection<TEntity>("quotes");
}
public string TestCallWithCasting()
{
var t1 = ((IMongoQueryable<Quote>)QueryableCollection).GroupBy(x => x._id).Select(x => x.First()._id).ToString();
return t1;
}
public string TestCallWithoutCasting()
{
try
{
return QueryableCollection.GroupBy(x => x._id).Select(x => x.First()._id).ToString();
}
catch (Exception ex)
{
return ex.Message;
}
}
}
public class Quote : IMongoDbEntity
{
public string _id { get; set; }
}
public interface IMongoDbEntity : IEntity
{
string _id { get; set; }
}
public interface IEntity
{
}
}
Looks like IMongoQueryable<T> behaves differently if T is only known to be an interface. TestCallWithoutCasting doesn't throw exception if you add class before IMongoDbEntity in TEntity : IMongoDbEntity.
So finally it's like:
public class Test<TEntity> where TEntity : class, IMongoDbEntity

C# method Linq variable return

hope your help :)
I search to make the result of the LinQ Variable bellow "ES" available in an other method.
public void Contract_ES(QCAlgorithm Algorithm_ES, Slice slice)
{
foreach(var chain in slice.FutureChains)
{
var ES = (from futuresContract in chain.Value.OrderBy(x => x.Expiry)
where futuresContract.Expiry > Algorithm_ES.Time.Date.AddDays(1)
select futuresContract).FirstOrDefault();
}
}
I downloaded QuantConnect just to get an idea what you're trying to do. The example below should at least not yield any errors, but I haven't tried the output.
using QuantConnect.Data;
using System.Linq;
using QuantConnect.Data.Market;
namespace QuantConnect.Algorithm
{
public interface IFuturesContractSelector_ES
{
FuturesContract GetFuturesContract_ES(QCAlgorithm Algorithm_ES, Slice slice);
}
public class Contract_ES : IFuturesContractSelector_ES
{
private readonly Slice _Slice;
private readonly QCAlgorithm _Algorithm_ES;
public Contract_ES(QCAlgorithm Algorithm_ES)
{
_Algorithm_ES = Algorithm_ES;
}
public Contract_ES(Slice slice)
{
_Slice = slice;
}
public FuturesContract GetFuturesContract_ES(QCAlgorithm Algorithm_ES, Slice slice)
{
foreach (var chain in slice.FutureChains)
{
if (chain.Value.Symbol.Value.StartsWith("ES"))
{
return (from futuresContract in chain.Value.OrderBy(x => x.Expiry)
where futuresContract.Expiry > Algorithm_ES.Time.Date.AddDays(1)
select futuresContract).FirstOrDefault();
}
}
return null;
}
}
}
Or you could do an extension on the Slice class:
using QuantConnect.Data;
using System.Linq;
using QuantConnect.Data.Market;
namespace QuantConnect.Algorithm
{
public static class SliceExtensions
{
public static FuturesContract GetFuturesContract_ES(this Slice slice, QCAlgorithm Algorithm_ES)
{
foreach (var chain in slice.FutureChains)
{
if (chain.Value.Symbol.Value.StartsWith("ES"))
{
return (from futuresContract in chain.Value.OrderBy(x => x.Expiry)
where futuresContract.Expiry > Algorithm_ES.Time.Date.AddDays(1)
select futuresContract).FirstOrDefault();
}
}
return null;
}
}
public class Test
{
public void TestMyMethod(Slice slice)
{
var contract = slice.GetFuturesContract_ES(new QCAlgorithm());
//... do something
}
}
}
I tried to create an interface then the method, result is :
using QuantConnect.Securities;
namespace Quant
{
public interface IFuturesContractSelector_ES
{
void GetFuturesContract_ES(QCAlgorithm Algorithm_ES, Slice slice);
}
}
public class Contract_ES : IFuturesContractSelector_ES
{
private readonly Slice _Slice;
private readonly QCAlgorithm _Algorithm_ES;
public Contract_ES(QCAlgorithm Algorithm_ES)
{
_Algorithm_ES = Algorithm_ES;
}
public Contract_ES(Slice slice)
{
_Slice = slice;
}
public void GetFuturesContract_ES(QCAlgorithm Algorithm_ES, Slice slice)
{
foreach(var chain in slice.FutureChains)
{
if (chain.Value.Symbol.StartsWith("ES"))
{
var ES = (from futuresContract in chain.Value.OrderBy(x => x.Expiry)
where futuresContract.Expiry > Algorithm_ES.Time.Date.AddDays(1)
select futuresContract).FirstOrDefault();
}
}
return ES;
}
}
At the Line return ES, I get this error :
The name "ES" does not exist in the current context.
Weird because I have another method build in this way, with no prob -_-
Maybe using foreach statement that cause the non possible return of "var ES" ?

Alias a model's property to a different name in asp.net-core

I wish to alias the name of my request object properties, so that these requests both work and both go to the same controller:
myapi/cars?colors=red&colors=blue&colors=green and myapi/cars?c=red&c=blue&c=green
for request object:
public class CarRequest {
Colors string[] { get; set; }
}
Has anyone been able to use the new ModelBinders to solve this without having to write ModelBindings from scratch?
Here is a similar problem for an older version of asp.net and also here
I wrote a model binder to do this:
EDIT:
Here's the repo on github. There are two nuget packages you can add to your code that solve this problem. Details in the readme
It basically takes the place of the ComplexTypeModelBinder (I'm too cowardly to replace it, but I slot it in front with identical criteria), except that it tries to use my new attribute to expand the fields it's looking for.
Binder:
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using MYDOMAIN.Client;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.Extensions.Logging;
namespace MYDOMAIN.Web.AliasModelBinder
{
public class AliasModelBinder : ComplexTypeModelBinder
{
public AliasModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders, ILoggerFactory loggerFactory,
bool allowValidatingTopLevelNodes)
: base(propertyBinders, loggerFactory, allowValidatingTopLevelNodes)
{
}
protected override Task BindProperty(ModelBindingContext bindingContext)
{
var containerType = bindingContext.ModelMetadata.ContainerType;
if (containerType != null)
{
var propertyType = containerType.GetProperty(bindingContext.ModelMetadata.PropertyName);
var attributes = propertyType.GetCustomAttributes(true);
var aliasAttributes = attributes.OfType<BindingAliasAttribute>().ToArray();
if (aliasAttributes.Any())
{
bindingContext.ValueProvider = new AliasValueProvider(bindingContext.ValueProvider,
bindingContext.ModelName, aliasAttributes.Select(attr => attr.Alias));
}
}
return base.BindProperty(bindingContext);
}
}
}
Provider:
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
using Microsoft.Extensions.Logging;
namespace MYDOMAIN.Web.AliasModelBinder
{
public class AliasModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType)
{
var propertyBinders = new Dictionary<ModelMetadata, IModelBinder>();
foreach (var property in context.Metadata.Properties)
{
propertyBinders.Add(property, context.CreateBinder(property));
}
return new AliasModelBinder(propertyBinders,
(ILoggerFactory) context.Services.GetService(typeof(ILoggerFactory)), true);
}
return null;
}
/// <summary>
/// Setup the AliasModelBinderProvider Mvc project to use BindingAlias attribute, to allow for aliasing property names in query strings
/// </summary>
public static void Configure(MvcOptions options)
{
// Place in front of ComplexTypeModelBinderProvider to replace this binder type in practice
for (int i = 0; i < options.ModelBinderProviders.Count; i++)
{
if (options.ModelBinderProviders[i] is ComplexTypeModelBinderProvider)
{
options.ModelBinderProviders.Insert(i, new AliasModelBinderProvider());
return;
}
}
options.ModelBinderProviders.Add(new AliasModelBinderProvider());
}
}
}
Value Provider:
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.Extensions.Primitives;
namespace MYDOMAIN.Web.AliasModelBinder
{
public class AliasValueProvider : IValueProvider
{
private readonly IValueProvider _provider;
private readonly string _originalName;
private readonly string[] _allNamesToBind;
public AliasValueProvider(IValueProvider provider, string originalName, IEnumerable<string> aliases)
{
_provider = provider;
_originalName = originalName;
_allNamesToBind = new[] {_originalName}.Concat(aliases).ToArray();
}
public bool ContainsPrefix(string prefix)
{
if (prefix == _originalName)
{
return _allNamesToBind.Any(_provider.ContainsPrefix);
}
return _provider.ContainsPrefix(prefix);
}
public ValueProviderResult GetValue(string key)
{
if (key == _originalName)
{
var results = _allNamesToBind.Select(alias => _provider.GetValue(alias)).ToArray();
StringValues values = results.Aggregate(values, (current, r) => StringValues.Concat(current, r.Values));
return new ValueProviderResult(values, results.First().Culture);
}
return _provider.GetValue(key);
}
}
}
And an attribute to go in / be referenced by the client project
using System;
namespace MYDOMAIN.Client
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class BindingAliasAttribute : Attribute
{
public string Alias { get; }
public BindingAliasAttribute(string alias)
{
Alias = alias;
}
}
}
Configured in the Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services
...
.AddMvcOptions(options =>
{
AliasModelBinderProvider.Configure(options);
...
})
...
Usage:
public class SomeRequest
{
[BindingAlias("f")]
public long[] SomeVeryLongNameForSomeKindOfFoo{ get; set; }
}
leading to a request that looks either like this:
api/controller/action?SomeVeryLongNameForSomeKindOfFoo=1&SomeVeryLongNameForSomeKindOfFoo=2
or
api/controller/action?f=1&f=2
I put most things in my web project, and the attribute in my client project.

ASP.NET and MongoDB - Not saving in the context of a Unit Test

I am new to MongoDB and setting up a .NET C# MVC Project to try it out.
Using the current MongoDB.Driver 2.2.2 from nuget.
Issue:
I have a unit test that succeeds but does not save any data to the MongoDB Collection.
[TestMethod]
public void TestMethod1()
{
IDatabase<Publisher> context = new MyProject.Data.Concrete.MongoDatabase<Publisher>("Publishers");
Publisher pub = new Publisher()
{
Name = "Test"
};
context.Add(pub);
}
However, if I put this same test under a MVC Controller it will save the data:
public ActionResult Contact() {
ViewBag.Message = "Your contact page.";
IDatabase<Publisher> context = new MyProject.Data.Concrete.MongoDatabase<Publisher>("Publishers");
Publisher pub = new Publisher()
{
Name = "Test"
};
context.Add(pub);
return View();
}
I am curious as to why this is so?
Here is the MongoDatabase class:
public class MongoDatabase<T> : IDatabase<T> where T : class, new()
{
private static string _connectionString = ConfigurationManager.ConnectionStrings["mongodb"].ConnectionString;
private MongoClient _mongoClient = new MongoClient(_connectionString);
private string _collectionName;
private IMongoDatabase _db;
protected IMongoCollection<T> _collection
{
get
{
return _db.GetCollection<T>(_collectionName);
}
set
{
_collection = value;
}
}
public IQueryable<T> Query
{
get
{
return _collection.AsQueryable<T>();
}
set
{
Query = value;
}
}
public MongoDatabase(string collectionName)
{
_collectionName = collectionName;
_db = _mongoClient.GetDatabase(MongoUrl.Create(_connectionString).DatabaseName);
}
public bool Add(T item)
{
var result = _collection.InsertOneAsync(item);
//return result. what can we use here?
return true;
}
public int Add(IEnumerable<T> items)
{
int count = 0;
foreach (T item in items)
{
if (Add(item))
{
count++;
}
}
return count;
}
}
1) You should change calls for async methods.
public async Task Add(T item)
{
await _collection.InsertOneAsync(item);
}
You can read more about async.
2)
//return result. what can we use here?
return true;
You don't need to return bool. You need to have exception handler on a top level.

How to make WCF set a connection string for use with EntityFramework

Using EntityFramework, I have an auto-generated file with:
namespace Chaos.Data
{
public partial class ChaosModel : OpenAccessContext, IChaosModelUnitOfWork
{
private static string connectionStringName = #"ChaosLibraryConnection";
private static BackendConfiguration backend = GetBackendConfiguration();
private static MetadataSource metadataSource = XmlMetadataSource.FromAssemblyResource("EntitiesModel.rlinq");
public ChaosModel()
:base(connectionStringName, backend, metadataSource)
{ }
public ChaosModel(string connection)
:base(connection, backend, metadataSource)
{ }
......................
In the WCF Service, I am using:
namespace Chaos.DataService
{
[ServiceContract]
public class ChaosService
{
[OperationContract]
public IEnumerable<Encountertime> GetEncounterTimes(DateTime? encountertime)
{
if (encountertime == null) return null;
using (var context = new ChaosModel())
{
var query = from et in context.Encountertimes
where et.Tencounter.Date == ((DateTime)encountertime).Date
select et;
var result = context.CreateDetachedCopy(query.ToList());
return result;
}
}
.............................
How can I make the WCF service on startup execute a method (once) that will return a new connection string so that I can change the calls to ChaosModel() to:
using (var context = new ChaosModel(connectionString))
(I am looking for a way to add a static constructor within the WCF service--or something better?).
(The method will determine the network I am on and construct an appropriate connection string to the network server.)
Note: I can make no changes to the auto-generated Entity file.
Use static constructor.
[ServiceContract]
public class ChaosService
{
private static string connectionString;
static ChaosService(){
connectionString = your logic...
}
[OperationContract]
public IEnumerable<Encountertime> GetEncounterTimes(DateTime? encountertime)
{
using (var context = new ChaosModel(connectionString))
{
...
}
}
}
or eventually a singleton pattern:
public class ConnectionInfo
{
public string ConnectionString { get; private set; }
private ConnectionInfo()
{
var connectionstring = string.Empty;
//some logic
this.ConnectionString = connectionstring;
}
private static ConnectionInfo current;
public static ConnectionInfo Current {
get {
if (current != null)
current = new ConnectionInfo();
return current;
}
}
}
[OperationContract]
public IEnumerable<Encountertime> GetEncounterTimes(DateTime? encountertime)
{
using (var context = new ChaosModel(ConnectionInfo.Current.ConnectionString))
{
...
}
}

Categories

Resources