I have Azure App services in my Xamarin application, and everything was working 100% until this morning.
After a while, I found, what looks like the SDK removing my database from local storage, as soon as I do the .GetSyncTable() call.
My service looks like this:
private readonly IMobileServiceSyncTable<User> _table;
private readonly IMobileServiceClient _client;
private readonly MobileServiceSQLiteStore _store;
private readonly ICryptography _cryptography;
private readonly ISettings _settings;
public UserService(
IMobileServiceClient client,
ICryptography cryptography)
{
_client = client;
_cryptography = cryptography;
_settings = new Settings(cryptography) as ISettings;
_store = new MobileServiceSQLiteStore(Settings.SyncDb);
_store.DefineTable<User>();
_client.SyncContext.InitializeAsync(_store);
_table = _client.GetSyncTable<User>();
}
and then I do an "All()", which looks like this:
public async Task<List<User>> All()
{
try
{
var users = await _table.ToListAsync(); // <- this throws "table" not defined
return users;
}
catch (SQLiteException sqlex)
{
Log.Warning("UserService", sqlex.Message);
}
catch (Exception ex)
{
Log.Warning("UserService", ex.Message);
}
}
I have been trying to figure this out, and I'm nowhere closer to a solution.
During my debug, if I land my debugger on the await, and interrogate the _store variable, my "user" table is defined, then a few seconds later, _store no longer contains my table.
I used ADB to download the local store, and viewed it in a SQLite manager, and the table is indeed defined, just, for some reason, it gets "lost"?
Any ideas would be greatly appreciated.
Per my understanding, the issue may caused by the InitializeAsync has not been initialized correctly. You just called _client.SyncContext.InitializeAsync(_store); in the constructor of UserService class. And you need to invoke await _client.SyncContext.InitializeAsync(_store); for initializing the store.
The common Offline Sync Initialization would look as follows:
async Task InitializeAsync()
{
// Short circuit - local database is already initialized
if (Client.SyncContext.IsInitialized)
return;
// Create a reference to the local sqlite store
var store = new MobileServiceSQLiteStore("offlinecache.db");
// Define the database schema
store.DefineTable<TodoItem>();
// Actually create the store and update the schema
await Client.SyncContext.InitializeAsync(store);
}
Here is a similar issue about wrapping the operations against Azure Cloud Table. Moreover, you could follow adrian hall's book about An Offline Client.
Related
I'm using the dotnet Testcontainers library to spin up a SQL Server database in Docker for integration testing. I'm using the MSTest framework.
My idea is to run a TestInitialize where the container will start, populate the database and run assertions in the test method, and then run a TestCleanup at the end which will stop the container and dispose of it.
However, the container starts up in Docker and the test hangs (I guess it never ends up running for some reason). Also I'm not 100% sure how to populate the database (I couldn't find any commands for initialising and SQL scripts).
Here is the code:
[TestClass]
public class WithFixtureData
{
private static readonly TestcontainersContainer _dbContainer =
new TestcontainersBuilder<TestcontainersContainer>()
.WithImage("mcr.microsoft.com/mssql/server")
.WithEnvironment("Database", "Master")
.WithEnvironment("User Id", "SA")
.WithEnvironment("Password", "YourSTRONG!Passw0rd")
.WithCleanUp(true)
.Build();
[TestInitialize]
public async Task StartContainer()
{
await _dbContainer.StartAsync();
///container starts
}
[TestMethod]
public async Task ShouldBringCorrectFixturesBack()
{
///populate db and run assertions. This code never seems to run
}
[TestCleanup]
public async Task DisposeContainer()
{
await _dbContainer.StopAsync();
///this part of the code never seems to be executed either
}
}
I am wondering how the example above even runs, the configuration looks wrong. I attached a working example below, but first, lets take a look into the issues:
The environment variables do not exist. The mcr.microsoft.com/mssql/server image has the following environment variables (see section Environment Variables) to configure SQL Server on Linux containers. The section How to use this Image might also help. To run the container at least these configurations are necessary:
.WithEnvironment("ACCEPT_EULA", "Y")
.WithEnvironment("MSSQL_SA_PASSWORD", "yourStrong(!)Password")
The database port is not exposed, you cannot connect to the database. To expose and bind a container port to a random public host port use .WithPortBinding(1433, true). Here is another example that shows how to expose a container port.
Your configuration does not use a wait strategy to indicate readiness of the service running inside the container. A wait strategy for SQL Server could be something like:
.WithWaitStrategy(Wait.ForUnixContainer().UntilCommandIsCompleted("/opt/mssql-tools/bin/sqlcmd", "-S", "localhost,1433", "-U", "sa", "-P", "yourStrong(!)Password"))
A working configuration will look something like:
[TestClass]
public sealed class SO
{
private const string Database = "master";
private const string Username = "sa";
private const string Password = "yourStrong(!)Password";
private const ushort MssqlContainerPort = 1433;
private readonly TestcontainersContainer _dbContainer =
new TestcontainersBuilder<TestcontainersContainer>()
.WithImage("mcr.microsoft.com/mssql/server:2022-latest")
.WithPortBinding(MssqlContainerPort, true)
.WithEnvironment("ACCEPT_EULA", "Y")
.WithEnvironment("MSSQL_SA_PASSWORD", Password)
.WithWaitStrategy(Wait.ForUnixContainer().UntilCommandIsCompleted("/opt/mssql-tools/bin/sqlcmd", "-S", $"localhost,{MssqlContainerPort}", "-U", Username, "-P", Password))
.Build();
[TestInitialize]
public Task StartContainer()
{
return _dbContainer.StartAsync();
}
[TestCleanup]
public Task DisposeContainer()
{
return _dbContainer.StopAsync();
}
[TestMethod]
public Task Question_74323116()
{
var connectionString = $"Server={_dbContainer.Hostname},{_dbContainer.GetMappedPublicPort(MssqlContainerPort)};Database={Database};User Id={Username};Password={Password};";
using (var sqlConnection = new SqlConnection(connectionString))
{
try
{
sqlConnection.Open();
}
catch
{
Assert.Fail("Could not establish database connection.");
}
}
return Task.CompletedTask;
}
}
I'm currently trying to implement a solution to read and write data to an Azure Redis cache. For the most part the implementation is complete however, when I attempt to read the redis cache I get an error of:
An unhandled host error has occured Newtonsoft.Json: Self referencing
loop detected for property 'target' with type
'System.Runtime.CompilerServices.AsyncTaskMethodBuilder'
1+AsyncStateMachineBox'1[System.String,
MyProject.Service.CarData.RedisCachService+d__2]'.
Path 'moveNextAction'.
Here is my code so far.
Method
private readonly IRedisService _redisService;
public Car(IRedisService redisService)
{
_redisService = redisService;
}
[FunctionName("GetCarData")]
public async Task<IActionResult> GetCarData([HttpTrigger(AuthorisationLevel.Anonymous, "get", Route = "v1/car/get")] HttpRequest req)
{
var data = _redisService.GetCarDataAsync("testId")
return new OkObjectResult(data)
}
Interface
public interface IRedisService
{
Task<string> GetCarDataAsync(string key)
}
Service
private readonly IConnectionMultiplexer _conn;
public RedisService(IConnectionMultiplexer conn)
{
_conn = conn;
}
public async Task<string> GetCarDataAsync(string key)
{
var data = _conn.GetDatabase();
return await db.StringGetAsync(key);
}
Startup
// Redis Information
services.AddSingleton<IRedisService, RedisService>();
services.AddSingleton<IConnectionMultiplexer>(x =>
ConnectionMultiplexer.Connect("Azure Redis host],abortConnection=false,ssl=true,password=[Primary Access Key]")
)
As this is a very basic function that simply requests data based on a key and also my first time implementing this, I'm not sure exactly what is causing the problem. Typically I've seen similar with models which reference each other but this is not the same. Has anyone had this before or can point me in the right direction?
I'm trying to integrate GitHubAPI in a web app that I am developing. I heard that the best way to do this in C# is using Octokit library but I can't find a very explicit documentation. Now, first of all I am trying to get a repo from GitHub. When I started, I manually accessed the endpoints as shown in the GitHub API. However, it seems that doing a commit that way is not possible so I switched to Octokit but I have some problems here.
Here is my OctokitGitService class:
*imports here*
namespace Web.Git.Api.Services;
public class OctokitGithubClient
{
private readonly Config _config;
private readonly GitHubClient _gitClient;
public List<Repository> Repositories { get; set; }
public OctokitGithubClient(IOptions<Config> options)
{
_config = options.Value;
var ghe = new Uri(_config.apiUrl);
_gitClient= new GitHubClient(new ProductHeaderValue("web-app-v1"), ghe);
var tokenAuth = new Credentials(_config.PAT.git);
_gitClient.Credentials = tokenAuth;
}
public async Task<List<Repository>> getGithubRepository()
{
var data = _gitClient.Repository.GetAllForCurrent();
Repositories = new List<Repository>(data);
return Repositories;
}
}
And I get this error message:
error CS0029: Cannot implicitly convert type 'System.Collections.Generic.List<Octokit.Repository>' to 'Octokit.Repository' [/root/projects/WebAppProject/src/Web.Git.Api/Web.Git.Api.csproj]
Can someone please give me a hint? I was looking through Octokit doc but I can't find API documentations. Ty!
You can read more about asynchronous programming in C#. Here is a good place to start.
GetAllForCurrent() signature is Task<IReadOnlyList<Repository>> GetAllForCurrent(); If we want to use this asynchronously, we use await and then we convert IReadOnlyList<Repository> to List<Repository> using ToList()
public async Task<List<Repository>> GetGithubRepositoryAsync()
{
var repos = await _gitClient.Repository.GetAllForCurrent();
return repos.ToList();
}
If we want to use it synchronously, one way is to use Result of the Task<>
public List<Repository> GetGithubRepository()
{
return _gitClient.Repository.GetAllForCurrent().Result.ToList();
}
As mentioned in this link using Result property is not recommended
The Result property is a blocking property. If you try to access it before its task is finished, the thread that's currently active is blocked until the task completes and the value is available. In most cases, you should access the value by using await instead of accessing the property directly.
I'm a noob when it comes to Blazor, and C# for that matter.
I'm trying to create a simple service. Simple process that includes running a stored procedure, and displaying its results in a table. I'm starting simple, by just making sure that the process runs.
Here's what my service looks like:
public class ACheckerService : IACheckerService
{
// Database connection
private readonly SqlConnectionConfig _config;
public ACheckerService(SqlConnectionConfig config)
{
_config = config;
}
public async Task<IEnumerable<AChecker>> GetAllExceptions()
{
IEnumerable<AChecker> exceptions;
using (var conn = new SqlConnection(_config.Value))
{
exceptions = await conn.QueryAsync<AChecker>("Auto.GetAll", commandType: System.Data.CommandType.StoredProcedure);
}
return exceptions.ToList(); ;
}
}
I created AChecker model class which comprises of the fields that are to be pulled in by the stored procedure. Just 4 fields.
Once I had this done, I added a Blazor component (.Razor)
This is what my code looks like:
#page "/Data/Auto"
#using AChecker.Data
#inject IACheckerService CheckerService
<h3>Auto</h3>
<p>This component demonstrates Auto Exceptions</p>
#if (aChecker is null)
{
<p><em>Loading....</em></p>
}
else
{
<p><em>Data....</em></p>
}
#code {
private IEnumerable<AChecker> aChecker;
protected override async Task OnInitializedAsync()
{
aChecker = await CheckerService.GetAllAutoExceptions();
}
}
I added this service in Startup.Cs like :
services.AddSingleton<ACheckerService>();
Is there any issue with the code above or why it would not work?
I have this service added in my app, basically when I click on the menu, I expect to see either Loading or Data (ideally down the road, I want to create a table and populate the fields from the stored procedure in it, there are 4 fields), however I get a bunch of errors:
InvalidOperationException: Cannot provide a value for property CheckerService on type AChecker.Pages.MyPages.Auto. There is no registered service of type AChecker.Data.IACheckerService
Try registering the service using this overload instead which specifies the interface and its concrete implementation:
services.AddSingleton<IACheckerService, ACheckerService>();
I have a WebAPI solution with an endpoint "DeleteFolder". That looks like this:
public FolderController()
{
_service = new DtoService();
}
[HttpDelete]
public HttpResponseMessage DeleteFolder(int id)
{
_service.DeleteFolder(id);
return Request.CreateResponse(HttpStatusCode.OK, "Deleted");
}
My _service is an instance of DtoService.cs which contains this:
public DtoService()
{
_repository = new RepositoryService();
}
public void DeleteFolder(int folderId)
{
_repository.DeleteFolder(folderId);
}
Finally, in my repository I have this:
public RepositoryService()
{
_db = new AppDbContext();
}
public void DeleteFolder(int folderId)
{
var folder = GetFolder(folderId);
_db.Folders.Remove(folder);
SaveChanges();
}
Where _db is an instance of my project's DbContext, defined once in the constructor of the Repository class.
When I send a bunch of asynchronous AJAX calls to the delete method, I get "The context cannot be used while the model is being created.". I can see a new instance of RepositoryService spinning up for each one, but if I set a breakpoint at
var folder = GetFolder(folderId);
and then step over, it's hit again, so it seems the other instance is trying to hit the same code before the first one completes, which is somehow causing this error to be thrown.
I don't have any references to my dbContext in my WebAPI layer or DTO service layer - and I'd prefer to keep it that way if possible. I tried wrapping the DeleteFolder code in a using (_db = new AppDbContext) but this didn't work either - and I feel like peppering all of my repository methods with a new dbcontext can't possibly be a recommended solution.
What's going on here? Any tips would be awesome, I'm totally at a loss here.
One thread is initializing your context in response to a request (it's a lengthy process), and another comes in attempting to use the context. The second request thinks the context is ready for use and you get this exception: “The context cannot be used while the model is being created.”
The following code shows how to force database initialization in EF Code First at start up:
protected void Application_Start() {
// ...
// Initializes and seeds the database.
Database.SetInitializer(new MyDBInitializer());
// Forces initialization of database on model changes.
using (var context = new ApplicationDB()) {
context.Database.Initialize(force: true);
}
// ...
}