xamarin.forms: retrieving existing data from .db file - database

In Xamarin Forms 4.3, I'm following this "Local Databases" doc: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/data-cloud/data/databases
This doc explains how to create and use a new sqlite db, but how do I go about in loading and displaying data in an existing .db file with the end purpose of transferring it into a new local sqlite database?
using SQLite;
namespace TruckExample.Models
{
public class Truck
{
[PrimaryKey, AutoIncrement]
public int TruckNo { get; set; }
public string TruckName { get; set; }
}
}
//////////////////////////////////////////////
using System.Collections.Generic;
using System.Threading.Tasks;
using SQLite;
using TruckExample.Models;
namespace TruckExample.Data
{
public class TruckDatabase
{
readonly SQLiteAsyncConnection _database;
public TruckDatabase(string dbPath)
{
_database = new SQLiteAsyncConnection(dbPath);
_database.CreateTableAsync<Truck>().Wait();
}
public Task<List<Truck>> GetTrucksAsync()
{
return _database.Table<Truck>().ToListAsync();
}
}
}
////////////////////////////////////////////////
using System;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using TruckExample.Data;
using System.IO;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace TruckExample
{
public partial class App : Application
{
static TruckDatabase database;
public static TruckDatabase Database
{
get
{
if(database == null)
{
database = new TruckDatabase(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Truck.db"));
}
return database;
}
}
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
}
}
/////////////////////////////////////////
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace TruckExample
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : ContentPage
{
public MainPage ()
{
InitializeComponent ();
}
protected override async void OnAppearing()
{
base.OnAppearing();
listView.ItemsSource = await App.Database.GetTrucksAsync();
Debug.Write(App.Database.GetTrucksAsync());
}
}
}

For others, helpful resources:
Implementation by Hameed Kunkanoor: "Creating a sqlite databse and storing your data in your android and ios application in Xamarin Forms" https://medium.com/#hameedkunkanoor/creating-a-sqlite-databse-and-storing-your-data-in-your-android-and-ios-application-in-xamarin-2ebaa79cdff0
(Refer to his git if needed)
Explanation/response by Matthewrdev: Use a local database in Xamarin
To improve the implementation -- Brandon Minnick: "Xamarin: Efficiently Using a SQLite Database" https://codetraveler.io/2019/11/26/efficiently-initializing-sqlite-database/

Related

How to validate if email attribute is unique in an ASP .NET CORE API?

I was needing to make a post or put a validation on the server side to check if the email is unique.
In the research I have always done the example was a traditional MVC application and never an api.
In many cases I saw that the [Remote] https://learn.microsoft.com/pt-br/aspnet/core/mvc/models/validation?view=aspnetcore-2.2#remote-attribute . I tried to implement according to the documentation, but debugging verified that the function in the controller is neither called.
User.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Mvc;
namespace Base.Models
{
[Table("users")]
public partial class User
{
...
[Required]
[EmailAddress]
[Remote(action: "VerifyEmail", controller: "UserController",ErrorMessage="Email already in use")]
[Column("email", TypeName = "varchar(254)")]
public string Email { get; set; }
...
}
}
UserController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Base.Models;
namespace Base.Controllers
{
[Route("api/users")]
[ApiController]
public class UserController : Controller
{
...
[AcceptVerbs("Get")]
public IActionResult VerifyEmail(string email)
{
//forcing it to go wrong
return Json($"Email {email} is already in use.");
}
...
}
}
Anyone have any idea how to implement this?
Seeing that it was not progressing, I decided to do a personalized validation.
EmailUserUniqueAttribute.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
using Base.Models;
namespace Core.Models
{
public class EmailUserUniqueAttribute : ValidationAttribute
{
protected override ValidationResult IsValid(
object value, ValidationContext validationContext)
{
var _context = (AppDbContext)validationContext.GetService(typeof(AppDbContext));
var entity = _context.Users.SingleOrDefault(e => e.Email == value.ToString());
if (entity != null)
{
return new ValidationResult(GetErrorMessage(value.ToString()));
}
return ValidationResult.Success;
}
public string GetErrorMessage(string email)
{
return $"Email {email} is already in use.";
}
}
}
User.cs
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.AspNetCore.Mvc;
namespace Base.Models
{
[Table("users")]
public partial class User
{
...
[Required]
[EmailAddress]
[EmailUserUnique]
[Column("email", TypeName = "varchar(254)")]
public string Email { get; set; }
}
}
...
It works, but I don't know if this is the best way to do this.
I cant comment cause I lack the sufficient reputation, and if I had time I would had gone and verified but I think your issue here is the [Route("api/users")].
You are giving your decorator the Controller name but that controller is behind a different route. Easy debug of that will be to remove the Route temporarily OR put the "VerifyEmail" action to another controller that you arent altering its route.

Textbox wont update

So i'm making a basic yahtzee program i c#, and im trying to make an actual gui and not just use the console. However i have a problem with the textbox. When i roll the dice, i want the textbox to display the number rolled. Now it shows nothing. I use two classes, one for the actual program and one for handling the gui. This is the yahtzee class:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Yahtzee
{
class YahtzeeScorer {
Random rndm = new Random();
Form1 gui = new Form1();
String dice1, dice2, dice3, dice4, dice5;
public void rollDice()
{
String a = Console.ReadLine();
this.dice1 = rndm.Next(1, 7).ToString();
this.gui.tbDice_SetText(this.dice1);
}
static void Main(String[] args) {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
YahtzeeScorer ys = new YahtzeeScorer();
Application.Run(ys.gui);
ys.rollDice();
Console.WriteLine("The result was: " + ys.dice1 );
Console.Read();
}
}
}
And this is the gui class form1:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Yahtzee
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void tbDice_SetText(String s)
{
//this.ActiveControl = tbDice;
Console.WriteLine("SetText");
tbDice.Text = s;
}
public void textBox1_TextChanged(object sender, EventArgs e)
{
}
}
}
tbDice is the name of the textbox component. Any ideas?
Examine the lines:
Application.Run(ys.gui);
ys.rollDice();
rollDice() will not be called until the application exits, because the thread running Main() will block on Application.Run() until it does.
Instead, try calling ys.rollDice() in something like a button event handler.
UPDATE
You are mixing your game logic and your presentation logic by putting both aspects in YahtzeeScorer. I would suggest that you move the game logic into a separate class like this:
public class YahtzeeGame
{
public string rollDice()
{
return rndm.Next(1, 7).ToString();
}
}
public partial class Form1 : Form
{
YahtzeeGame game = new YahtzeeGame();
public Form1()
{
InitializeComponent();
}
// You need to create a new Button on your form called btnRoll and
// add this as its click handler:
public void btnRoll_Clicked(object sender, EventArgs e)
{
tbDice.Text = game.rollDice();
}
}

WP7 background agent database access

I'm a beginner programmer in C#, so I think that the solution of my question might be easy, but after looking for it for days, I have not found anything that worked for me.
I have a WP7 app that contains a DB created with SQL CE.
CLASS PorniBD.cs
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Data.Linq.Mapping;
namespace PhoneClassLibrary1
{
[Table(Name = "Papilleros")]
public class PorniBD
{
[Column(IsPrimaryKey = true, IsDbGenerated = true)]
public int Id { get; set; }
[Column(CanBeNull = false)]
public String Nombre { get; set; }
[Column(CanBeNull = false)]
public String FechaNac { get; set; }
[Column(CanBeNull = false)]
public Boolean Activo { get; set; }
[Column(CanBeNull = false)]
public String Icono { get; set; }
}
}
CLASS PorniContext.cs
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Data.Linq.Mapping;
using System.Data.Linq;
namespace PhoneClassLibrary1
{
public class PorniContext : DataContext
{
public PorniContext(string connectionString) : base(connectionString)
{
//
}
public Table<PorniBD> Papilleros
{
get
{
return this.GetTable<PorniBD>();
}
}
}
}
My app has a background agent created in another project like I have learned in this page: Link
Now, I need to read app DB from background agent, and this class contains following OnInvoke void:
protected override void OnInvoke(ScheduledTask task)
{
List<PorniBD> listapapilleros = new List<PorniBD>();
using (PorniContext basedatos = new PorniContext("Data Source='isostore:/basedatos.sdf'"))
{
listapornis = basedatos.Papilleros.ToList();
}
// Launch a toast to show that the agent is running.
// The toast will not be shown if the foreground application is running.
ScheduledActionService.LaunchForTest(task.Name, TimeSpan.FromSeconds(10));
NotifyComplete();
}
but it's impossible because DataSource isolated is different in each project (I think), and I suppose that it's necessary to fix something more...
Thanks a lot for your help, and sorry if my English level is makes my explanation a bit difficult to understand...
Simply create a third project, of type "Windows Phone Class Library". Move your database code in that third project, then reference it from both your main project and your background agent project.

How to fix an error in the WPF design with custom control

I am attempting to create a region control that does the following trick
<wgc:RegionContentControl Region="HotDog">
<Label>Foo</Label>
<Label>Bar</Label>
</wgc:RegionContentControl>
<wgc:RegionControl Region="HotDog">
</wgc:RegionControl>
At run time and design time the controls defined in RegionContentControl
will get appended to RegionControl. I can use this to inject stuff into
status bars for example.
Anyway at runtime it works fine and sometimes in the designer it work.
However sometimes in the designer I get an error that
Element already has a logical parent. It must be detached from the
old parent before it is attached to the new one.
My code implementing the above pattern is below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace My.Controls
{
public class RegionMessage {
public enum RegionAction {
Add,
Remove,
}
public string Region { get; set; }
public List<Control> Controls { get; set; }
public RegionAction Action { get; set; }
}
public class RegionControl : ItemsControl
{
public RegionControl()
{
ReactiveUI
.MessageBus.Current
.Listen<RegionMessage>()
.Subscribe(HandleRegionMessage);
}
public string Region
{
get { return (string)GetValue(RegionProperty); }
set { SetValue(RegionProperty, value); }
}
public static readonly DependencyProperty RegionProperty =
DependencyProperty.Register("Region", typeof(string), typeof(RegionControl), new PropertyMetadata(""));
private void HandleRegionMessage(RegionMessage obj)
{
if (obj.Region!=Region)
{
return;
}
if (obj.Action==RegionMessage.RegionAction.Add)
{
foreach (var item in obj.Controls)
{
this.Items.Add(item);
}
}
else
{
foreach (var item in obj.Controls)
{
this.Items.Remove(item);
}
}
}
}
[ContentProperty("Children")]
public class RegionContentControl : Control
{
static RegionContentControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(RegionContentControl), new FrameworkPropertyMetadata(typeof(RegionContentControl)));
}
public static readonly DependencyProperty ChildrenProperty =
DependencyProperty.Register("Children", typeof(List<Control>), typeof(RegionContentControl), new PropertyMetadata(new List<Control>()));
public List<Control> Children
{
get { return (List<Control>)GetValue(ChildrenProperty); }
set { SetValue(ChildrenProperty, value); }
}
public string Region
{
get { return (string)GetValue(RegionProperty); }
set { SetValue(RegionProperty, value); }
}
// Using a DependencyProperty as the backing store for Region. This enables animation, styling, binding, etc...
public static readonly DependencyProperty RegionProperty =
DependencyProperty.Register("Region", typeof(string), typeof(RegionContentControl), new PropertyMetadata(""));
public RegionContentControl()
{
this.LoadedObserver().Subscribe(Loaded);
}
private void Loaded(System.Reactive.EventPattern<RoutedEventArgs> obj)
{
ReactiveUI.MessageBus.Current.SendMessage(new RegionMessage()
{
Action = RegionMessage.RegionAction.Add
,
Controls = Children
,
Region = Region
});
}
}
}
I am sure that my problem involves that the controls still think they are attached to the RegionContentControl but I'm not sure how to detach them correctly. Any suggestions?
Removing the items from Children before broadcasting does the trick
List<Control> _HiddenChildren;
private void Loaded(System.Reactive.EventPattern<RoutedEventArgs> obj)
{
if (_HiddenChildren==null)
{
_HiddenChildren = Children;
this.Children = new List<Control>();
}
ReactiveUI.MessageBus.Current.SendMessage(new RegionMessage()
{ Action = RegionMessage.RegionAction.Add
, Controls = _HiddenChildren
, Region = Region
});
}

How set EnqueueCallBack to my generic callback

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsistec.Domain;
using Microsistec.Client;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Collections.Generic;
using Microsistec.Tools;
using System.Json;
using Microsistec.SystemConfig;
using System.Threading;
using Microsoft.Silverlight.Testing;
namespace Test
{
[TestClass]
public class SampleTest : SilverlightTest
{
[TestMethod, Asynchronous]
public void login()
{
List<PostData> data = new List<PostData>();
data.Add(new PostData("email", "xxx"));
data.Add(new PostData("password", MD5.GetHashString("xxx")));
WebClient.sendData(Config.DataServerURL + "/user/login", data, LoginCallBack);
EnqueueCallback(?????????);
EnqueueTestComplete();
}
[Asynchronous]
public void LoginCallBack(object sender, System.Net.UploadStringCompletedEventArgs e)
{
string json = Microsistec.Client.WebClient.ProcessResult(e);
var result = JsonArray.Parse(json);
Assert.Equals("1", result["value"].ToString());
TestComplete();
}
}
Im tring to set ???????? value but my callback is generic, it is setup on my WebClient .SendData, how i implement my EnqueueCallback to a my already functio LoginCallBack???
You have to take a different approach to make this work. Why do you want to enqueue LoginCallBack? It would get called asynchronously when sendData has ended, would it not?
Also, I see no point in having a TestComplete() in LoginCallBack and EnqueueTestComplete() in login. Would this not work:
[TestClass]
public class SampleTest : SilverlightTest
{
[TestMethod, Asynchronous]
public void login()
{
List<PostData> data = new List<PostData>();
data.Add(new PostData("email", "xxx"));
data.Add(new PostData("password", MD5.GetHashString("xxx")));
WebClient.sendData(Config.DataServerURL + "/user/login", data, LoginCallBack);
}
[Asynchronous]
public void LoginCallBack(object sender, System.Net.UploadStringCompletedEventArgs e)
{
string json = Microsistec.Client.WebClient.ProcessResult(e);
var result = JsonArray.Parse(json);
Assert.Equals("1", result["value"].ToString());
TestComplete();
}
}
I'm unsure of how LoginCallback gets called but if you make sure that that happens it should make the test pass!

Resources