Xamarin.Mac'te Veritabanları
Bu makalede, SQLite veritabanları ile Xcode'un veri kaynağında kullanıcı arabirimi öğeleri arasında veri bağlamaya olanak sağlayan anahtar-değer kodlama ve anahtar-değer gözlemleme Interface Builder. Ayrıca SQLite verilerine erişim SQLite.NET orM'nin nasıl kullanılamayacaklarını da kapsar.
Genel Bakış
Bir Xamarin.Mac uygulamasında C# ve .NET ile çalışırken, bir Xamarin.iOS veya Xamarin.Android uygulamasının erişe çalıştığı SQLite veritabanlarına erişiminiz olur.
Bu makalede SQLite verilerine erişmenin iki yolu açıklanmıştır:
- Doğrudan Erişim - Bir SQLite Veritabanına doğrudan erişerek, Xcode'un veri kaynağında oluşturulan kullanıcı arabirimi öğeleriyle anahtar-değer kodlama ve veri bağlama için veritabanındaki verileri Interface Builder. Xamarin.Mac uygulamanıza anahtar-değer kodlama ve veri bağlama tekniklerini kullanarak kullanıcı arabirimi öğelerini doldurmak ve bu öğelerle çalışmak için yazmanız ve sürdürmeniz gereken kod miktarını önemli ölçüde azaltabilirsiniz. Ayrıca, arka uç verilerinizi(Veri Modeli ) ön uç Kullanıcı Arabirimi (Model-View-Controller)daha kolay ve daha esnek bir uygulama tasarımına neden olacak şekilde daha fazla şekilde aynabileceksiniz.
- SQLite.NET ORM- Açık kaynak SQLite.NET İlişki Yöneticisi'ni (ORM) kullanarak SQLite veritabanından veri okumak ve yazmak için gereken kod miktarını önemli ölçüde azaltabilirsiniz. Bu veriler daha sonra Tablo Görünümü gibi bir kullanıcı arabirimi öğesini doldurmak için kullanılabilir.
Bu makalede, bir Xamarin.Mac uygulamasında SQLite Veritabanları ile anahtar-değer kodlama ve veri bağlama ile çalışmayla ilgili temel bilgileri üzerinde çalışabilirsiniz. Öncelikle Hello, Mac makalesi, özellikle de Xcode'a giriş ve Interface Builder ve Çıkışlar ve Eylemler bölümlerine bakarak bu makalede kullanacaklarımız temel kavramları ve teknikleri gözden geçirin.
Anahtar-değer kodlamasını ve veri bağlamayı kullanmayacaksanız lütfen önce Veri bağlama ve anahtar-değer kodlaması üzerinde çalışın çünkü bu belgelerde ve örnek uygulamasında kullanılacak temel teknikler ve kavramlar ele alınmaktadır.
Exposing C# classes / methods to Objective-CExposing C# classes / methods to Objective-C belgesinin C# sınıflarınızı nesnelere ve kullanıcı arabirimi öğelerine kablolamak için kullanılan ve özniteliklerini de açıklayan bölümüne göz RegisterExportObjective-C atabilirsiniz.
Doğrudan SQLite erişimi
Xcode'un Interface Builder'sinde kullanıcı arabirimi öğelerine bağlanacak SQLite verileri için, verilerin yazıldığı ve veritabanından okunma yöntemi üzerinde tam denetime sahip olduğunuz için SQLite veritabanına doğrudan (ORM gibi bir teknik kullanmak yerine) erişmeyi kesinlikle önerebilirsiniz.
Veri Bağlama ve Key-Value Kodlama belgelerinde de olduğu gibi, Xamarin.Mac uygulamanıza anahtar-değer kodlama ve veri bağlama tekniklerini kullanarak, kullanıcı arabirimi öğelerini doldurmak ve bu öğelerle çalışmak için yazmanız ve sürdürmeniz gereken kod miktarını önemli ölçüde azaltabilirsiniz. Bir SQLite veritabanına doğrudan erişimle birlikte, bu veritabanına veri okumak ve yazmak için gereken kod miktarını büyük ölçüde azaltabilir.
Bu makalede, veri bağlama ve anahtar-değer kodlama belgesinde yer alan örnek uygulamayı, bağlama için destek kaynağı olarak bir SQLite Veritabanı kullanmak üzere değiştireceksiniz.
SQLite veritabanı desteği dahil
Devam etmek için, birkaç 'a Başvurular'ı dahil etmek için uygulamamıza SQLite veritabanı desteği eklememiz gerekir. DLL dosyaları.
Şunları yapın:
Giriş Çözüm Bölmesi,Başvurular klasörüne sağ tıklayın ve Başvuruları Düzenle'yi seçin.
Mono.Data.Sqlite veSystem.Data derlemelerini seçin:
Değişikliklerinizi kaydetmek ve başvuruları eklemek için Tamam düğmesine tıklayın.
Veri modelini değiştirme
Uygulamamıza doğrudan bir SQLite veritabanına erişim desteği ekleyişimizin yanı sıra veritabanından veri okumak ve yazmak için Veri Modeli Nesnemizi değiştirmemiz gerekir (ayrıca anahtar-değer kodlama ve veri bağlama sağlar). Örnek uygulamamız için PersonModel.cs sınıfını düzenleyemez ve aşağıdaki gibi olacak şekilde değiştirebilirsiniz:
using System;
using System.Data;
using System.IO;
using Mono.Data.Sqlite;
using Foundation;
using AppKit;
namespace MacDatabase
{
[Register("PersonModel")]
public class PersonModel : NSObject
{
#region Private Variables
private string _ID = "";
private string _managerID = "";
private string _name = "";
private string _occupation = "";
private bool _isManager = false;
private NSMutableArray _people = new NSMutableArray();
private SqliteConnection _conn = null;
#endregion
#region Computed Properties
public SqliteConnection Conn {
get { return _conn; }
set { _conn = value; }
}
[Export("ID")]
public string ID {
get { return _ID; }
set {
WillChangeValue ("ID");
_ID = value;
DidChangeValue ("ID");
}
}
[Export("ManagerID")]
public string ManagerID {
get { return _managerID; }
set {
WillChangeValue ("ManagerID");
_managerID = value;
DidChangeValue ("ManagerID");
}
}
[Export("Name")]
public string Name {
get { return _name; }
set {
WillChangeValue ("Name");
_name = value;
DidChangeValue ("Name");
// Save changes to database?
if (_conn != null) Update (_conn);
}
}
[Export("Occupation")]
public string Occupation {
get { return _occupation; }
set {
WillChangeValue ("Occupation");
_occupation = value;
DidChangeValue ("Occupation");
// Save changes to database?
if (_conn != null) Update (_conn);
}
}
[Export("isManager")]
public bool isManager {
get { return _isManager; }
set {
WillChangeValue ("isManager");
WillChangeValue ("Icon");
_isManager = value;
DidChangeValue ("isManager");
DidChangeValue ("Icon");
// Save changes to database?
if (_conn != null) Update (_conn);
}
}
[Export("isEmployee")]
public bool isEmployee {
get { return (NumberOfEmployees == 0); }
}
[Export("Icon")]
public NSImage Icon {
get {
if (isManager) {
return NSImage.ImageNamed ("group.png");
} else {
return NSImage.ImageNamed ("user.png");
}
}
}
[Export("personModelArray")]
public NSArray People {
get { return _people; }
}
[Export("NumberOfEmployees")]
public nint NumberOfEmployees {
get { return (nint)_people.Count; }
}
#endregion
#region Constructors
public PersonModel ()
{
}
public PersonModel (string name, string occupation)
{
// Initialize
this.Name = name;
this.Occupation = occupation;
}
public PersonModel (string name, string occupation, bool manager)
{
// Initialize
this.Name = name;
this.Occupation = occupation;
this.isManager = manager;
}
public PersonModel (string id, string name, string occupation)
{
// Initialize
this.ID = id;
this.Name = name;
this.Occupation = occupation;
}
public PersonModel (SqliteConnection conn, string id)
{
// Load from database
Load (conn, id);
}
#endregion
#region Array Controller Methods
[Export("addObject:")]
public void AddPerson(PersonModel person) {
WillChangeValue ("personModelArray");
isManager = true;
_people.Add (person);
DidChangeValue ("personModelArray");
}
[Export("insertObject:inPersonModelArrayAtIndex:")]
public void InsertPerson(PersonModel person, nint index) {
WillChangeValue ("personModelArray");
_people.Insert (person, index);
DidChangeValue ("personModelArray");
}
[Export("removeObjectFromPersonModelArrayAtIndex:")]
public void RemovePerson(nint index) {
WillChangeValue ("personModelArray");
_people.RemoveObject (index);
DidChangeValue ("personModelArray");
}
[Export("setPersonModelArray:")]
public void SetPeople(NSMutableArray array) {
WillChangeValue ("personModelArray");
_people = array;
DidChangeValue ("personModelArray");
}
#endregion
#region SQLite Routines
public void Create(SqliteConnection conn) {
// Clear last connection to prevent circular call to update
_conn = null;
// Create new record ID?
if (ID == "") {
ID = Guid.NewGuid ().ToString();
}
// Execute query
conn.Open ();
using (var command = conn.CreateCommand ()) {
// Create new command
command.CommandText = "INSERT INTO [People] (ID, Name, Occupation, isManager, ManagerID) VALUES (@COL1, @COL2, @COL3, @COL4, @COL5)";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", ID);
command.Parameters.AddWithValue ("@COL2", Name);
command.Parameters.AddWithValue ("@COL3", Occupation);
command.Parameters.AddWithValue ("@COL4", isManager);
command.Parameters.AddWithValue ("@COL5", ManagerID);
// Write to database
command.ExecuteNonQuery ();
}
conn.Close ();
// Save children to database as well
for (nuint n = 0; n < People.Count; ++n) {
// Grab person
var Person = People.GetItem<PersonModel>(n);
// Save manager ID and create the sub record
Person.ManagerID = ID;
Person.Create (conn);
}
// Save last connection
_conn = conn;
}
public void Update(SqliteConnection conn) {
// Clear last connection to prevent circular call to update
_conn = null;
// Execute query
conn.Open ();
using (var command = conn.CreateCommand ()) {
// Create new command
command.CommandText = "UPDATE [People] SET Name = @COL2, Occupation = @COL3, isManager = @COL4, ManagerID = @COL5 WHERE ID = @COL1";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", ID);
command.Parameters.AddWithValue ("@COL2", Name);
command.Parameters.AddWithValue ("@COL3", Occupation);
command.Parameters.AddWithValue ("@COL4", isManager);
command.Parameters.AddWithValue ("@COL5", ManagerID);
// Write to database
command.ExecuteNonQuery ();
}
conn.Close ();
// Save children to database as well
for (nuint n = 0; n < People.Count; ++n) {
// Grab person
var Person = People.GetItem<PersonModel>(n);
// Update sub record
Person.Update (conn);
}
// Save last connection
_conn = conn;
}
public void Load(SqliteConnection conn, string id) {
bool shouldClose = false;
// Clear last connection to prevent circular call to update
_conn = null;
// Is the database already open?
if (conn.State != ConnectionState.Open) {
shouldClose = true;
conn.Open ();
}
// Execute query
using (var command = conn.CreateCommand ()) {
// Create new command
command.CommandText = "SELECT * FROM [People] WHERE ID = @COL1";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", id);
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Pull values back into class
ID = (string)reader [0];
Name = (string)reader [1];
Occupation = (string)reader [2];
isManager = (bool)reader [3];
ManagerID = (string)reader [4];
}
}
}
// Is this a manager?
if (isManager) {
// Yes, load children
using (var command = conn.CreateCommand ()) {
// Create new command
command.CommandText = "SELECT ID FROM [People] WHERE ManagerID = @COL1";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", id);
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Load child and add to collection
var childID = (string)reader [0];
var person = new PersonModel (conn, childID);
_people.Add (person);
}
}
}
}
// Should we close the connection to the database
if (shouldClose) {
conn.Close ();
}
// Save last connection
_conn = conn;
}
public void Delete(SqliteConnection conn) {
// Clear last connection to prevent circular call to update
_conn = null;
// Execute query
conn.Open ();
using (var command = conn.CreateCommand ()) {
// Create new command
command.CommandText = "DELETE FROM [People] WHERE (ID = @COL1 OR ManagerID = @COL1)";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", ID);
// Write to database
command.ExecuteNonQuery ();
}
conn.Close ();
// Empty class
ID = "";
ManagerID = "";
Name = "";
Occupation = "";
isManager = false;
_people = new NSMutableArray();
// Save last connection
_conn = conn;
}
#endregion
}
}
Şimdi aşağıdaki değişikliklere ayrıntılı bir şekilde göz atacağız.
İlk olarak, SQLite kullanmak için gereken birkaç using deyimi ekledik ve SQLite veritabanına son bağlantımızı kaydetmek için bir değişken ekledik:
using System.Data;
using System.IO;
using Mono.Data.Sqlite;
...
private SqliteConnection _conn = null;
Kullanıcı, kullanıcı arabiriminde veri bağlama yoluyla içeriği değiştirirken kayıtta yapılan değişiklikleri otomatik olarak kaydetmek için bu kayıtlı bağlantıyı kullanacaktır:
[Export("Name")]
public string Name {
get { return _name; }
set {
WillChangeValue ("Name");
_name = value;
DidChangeValue ("Name");
// Save changes to database?
if (_conn != null) Update (_conn);
}
}
[Export("Occupation")]
public string Occupation {
get { return _occupation; }
set {
WillChangeValue ("Occupation");
_occupation = value;
DidChangeValue ("Occupation");
// Save changes to database?
if (_conn != null) Update (_conn);
}
}
[Export("isManager")]
public bool isManager {
get { return _isManager; }
set {
WillChangeValue ("isManager");
WillChangeValue ("Icon");
_isManager = value;
DidChangeValue ("isManager");
DidChangeValue ("Icon");
// Save changes to database?
if (_conn != null) Update (_conn);
}
}
Ad ,Meslek veya isManager özelliklerinde yapılan tüm değişiklikler, veriler daha önce buraya kaydedildiyse veritabanına gönderilir (örneğin, değişken değilse). Şimdi Oluşturma, Güncelleştirme, Yükleme ve Silme'ye ekleyemedik yöntemlere bakalım.
Yeni kayıt oluşturma
SQLite veritabanında yeni bir kayıt oluşturmak için aşağıdaki kod eklenmiştir:
public void Create(SqliteConnection conn) {
// Clear last connection to prevent circular call to update
_conn = null;
// Create new record ID?
if (ID == "") {
ID = Guid.NewGuid ().ToString();
}
// Execute query
conn.Open ();
using (var command = conn.CreateCommand ()) {
// Create new command
command.CommandText = "INSERT INTO [People] (ID, Name, Occupation, isManager, ManagerID) VALUES (@COL1, @COL2, @COL3, @COL4, @COL5)";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", ID);
command.Parameters.AddWithValue ("@COL2", Name);
command.Parameters.AddWithValue ("@COL3", Occupation);
command.Parameters.AddWithValue ("@COL4", isManager);
command.Parameters.AddWithValue ("@COL5", ManagerID);
// Write to database
command.ExecuteNonQuery ();
}
conn.Close ();
// Save children to database as well
for (nuint n = 0; n < People.Count; ++n) {
// Grab person
var Person = People.GetItem<PersonModel>(n);
// Save manager ID and create the sub record
Person.ManagerID = ID;
Person.Create (conn);
}
// Save last connection
_conn = conn;
}
Veritabanında yeni SQLiteCommand kayıt oluşturmak için kullanıyoruz. çağrısıyla yöntemine geçirilen SQLiteConnection (conn) komutundan yeni bir komut alır. CreateCommand Ardından, gerçek SQL parametreleri sağlayarak yeni kaydı gerçekten yazacak şekilde SQL yönergesi ayarlayacağız:
command.CommandText = "INSERT INTO [People] (ID, Name, Occupation, isManager, ManagerID) VALUES (@COL1, @COL2, @COL3, @COL4, @COL5)";
Daha sonra, üzerinde yöntemini kullanarak Parameters.AddWithValue parametrelerin değerlerini SQLiteCommand ayarlayacağız. Parametreleri kullanarak değerlerin (tek tırnak gibi) SQLite'a gönderilmeden önce düzgün bir şekilde kodlanmasına izin veririz. Örnek:
command.Parameters.AddWithValue ("@COL1", ID);
Son olarak, bir kişi yönetici olabilir ve altında çalışan koleksiyonuna sahip olabilir, bu kişilerin veritabanına da kaydetmesi için yöntemini tekrar tekrar Create çağırıyoruz:
// Save children to database as well
for (nuint n = 0; n < People.Count; ++n) {
// Grab person
var Person = People.GetItem<PersonModel>(n);
// Save manager ID and create the sub record
Person.ManagerID = ID;
Person.Create (conn);
}
Kaydı güncelleştirme
SQLite veritabanındaki mevcut bir kaydı güncelleştirmek için aşağıdaki kod eklenmiştir:
public void Update(SqliteConnection conn) {
// Clear last connection to prevent circular call to update
_conn = null;
// Execute query
conn.Open ();
using (var command = conn.CreateCommand ()) {
// Create new command
command.CommandText = "UPDATE [People] SET Name = @COL2, Occupation = @COL3, isManager = @COL4, ManagerID = @COL5 WHERE ID = @COL1";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", ID);
command.Parameters.AddWithValue ("@COL2", Name);
command.Parameters.AddWithValue ("@COL3", Occupation);
command.Parameters.AddWithValue ("@COL4", isManager);
command.Parameters.AddWithValue ("@COL5", ManagerID);
// Write to database
command.ExecuteNonQuery ();
}
conn.Close ();
// Save children to database as well
for (nuint n = 0; n < People.Count; ++n) {
// Grab person
var Person = People.GetItem<PersonModel>(n);
// Update sub record
Person.Update (conn);
}
// Save last connection
_conn = conn;
}
Yukarıda oluştur'da olduğu gibi, geçirilen 'den bir alır ve kayıt SQL SQLiteConnection (parametre sağlayarak) olarak ayarlamamız gerekir:
command.CommandText = "UPDATE [People] SET Name = @COL2, Occupation = @COL3, isManager = @COL4, ManagerID = @COL5 WHERE ID = @COL1";
Parametre değerlerini (örnek: ) doldururuz ve tüm alt kayıtlarda yine yine command.Parameters.AddWithValue ("@COL1", ID); güncelleştirmeyi tekrarlarız:
// Save children to database as well
for (nuint n = 0; n < People.Count; ++n) {
// Grab person
var Person = People.GetItem<PersonModel>(n);
// Update sub record
Person.Update (conn);
}
Kayıt yükleme
SQLite veritabanından mevcut bir kaydı yüklemek için aşağıdaki kod eklenmiştir:
public void Load(SqliteConnection conn, string id) {
bool shouldClose = false;
// Clear last connection to prevent circular call to update
_conn = null;
// Is the database already open?
if (conn.State != ConnectionState.Open) {
shouldClose = true;
conn.Open ();
}
// Execute query
using (var command = conn.CreateCommand ()) {
// Create new command
command.CommandText = "SELECT * FROM [People] WHERE ID = @COL1";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", id);
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Pull values back into class
ID = (string)reader [0];
Name = (string)reader [1];
Occupation = (string)reader [2];
isManager = (bool)reader [3];
ManagerID = (string)reader [4];
}
}
}
// Is this a manager?
if (isManager) {
// Yes, load children
using (var command = conn.CreateCommand ()) {
// Create new command
command.CommandText = "SELECT ID FROM [People] WHERE ManagerID = @COL1";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", id);
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Load child and add to collection
var childID = (string)reader [0];
var person = new PersonModel (conn, childID);
_people.Add (person);
}
}
}
}
// Should we close the connection to the database
if (shouldClose) {
conn.Close ();
}
// Save last connection
_conn = conn;
}
Yordam bir üst nesneden (çalışan nesnesini yüklayan bir yönetici nesnesi gibi) tekrar tekrar çağrılanana kadar, veritabanı bağlantısının açılmasını ve kapatılmasını işlemek için özel kod eklendi:
bool shouldClose = false;
...
// Is the database already open?
if (conn.State != ConnectionState.Open) {
shouldClose = true;
conn.Open ();
}
...
// Should we close the connection to the database
if (shouldClose) {
conn.Close ();
}
Her zaman olduğu gibi, kaydı almak SQL ve parametreleri kullanmak için veri kümemizi ayarlamız:
// Create new command
command.CommandText = "SELECT ID FROM [People] WHERE ManagerID = @COL1";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", id);
Son olarak, sorguyu yürütmek ve kayıt alanlarını (sınıfının örneğine kopyalayıp) iade etmek için Bir Veri Okuyucusu PersonModel kullanıruz:
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Pull values back into class
ID = (string)reader [0];
Name = (string)reader [1];
Occupation = (string)reader [2];
isManager = (bool)reader [3];
ManagerID = (string)reader [4];
}
}
Bu kişi bir yönetici ise, tüm çalışanlarını da (yine kendi yöntemini tekrar tekrar çağırarak) yüklememiz Load gerekir:
// Is this a manager?
if (isManager) {
// Yes, load children
using (var command = conn.CreateCommand ()) {
// Create new command
command.CommandText = "SELECT ID FROM [People] WHERE ManagerID = @COL1";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", id);
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Load child and add to collection
var childID = (string)reader [0];
var person = new PersonModel (conn, childID);
_people.Add (person);
}
}
}
}
Kayıt silme
Mevcut bir kaydı SQLite veritabanından silmek için aşağıdaki kod eklenmiştir:
public void Delete(SqliteConnection conn) {
// Clear last connection to prevent circular call to update
_conn = null;
// Execute query
conn.Open ();
using (var command = conn.CreateCommand ()) {
// Create new command
command.CommandText = "DELETE FROM [People] WHERE (ID = @COL1 OR ManagerID = @COL1)";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", ID);
// Write to database
command.ExecuteNonQuery ();
}
conn.Close ();
// Empty class
ID = "";
ManagerID = "";
Name = "";
Occupation = "";
isManager = false;
_people = new NSMutableArray();
// Save last connection
_conn = conn;
}
Burada hem yönetici SQL hem de bu yönetici altındaki tüm çalışanların kayıtlarını silmek için gerekli bilgileri sağlarız (parametreleri kullanarak):
// Create new command
command.CommandText = "DELETE FROM [People] WHERE (ID = @COL1 OR ManagerID = @COL1)";
// Populate with data from the record
command.Parameters.AddWithValue ("@COL1", ID);
Kayıt kaldırıldıktan sonra sınıfının geçerli örneğini PersonModel temizlriz:
// Empty class
ID = "";
ManagerID = "";
Name = "";
Occupation = "";
isManager = false;
_people = new NSMutableArray();
Veritabanını başlatma
Veritabanına okuma ve yazma desteği için Veri Modelimizde yapılan değişikliklerle, veritabanına bir bağlantı açıp ilk çalıştırmada başlatmamız gerekir. MainWindow.cs dosyamıza aşağıdaki kodu ekalım:
using System.Data;
using System.IO;
using Mono.Data.Sqlite;
...
private SqliteConnection DatabaseConnection = null;
...
private SqliteConnection GetDatabaseConnection() {
var documents = Environment.GetFolderPath (Environment.SpecialFolder.Desktop);
string db = Path.Combine (documents, "People.db3");
// Create the database if it doesn't already exist
bool exists = File.Exists (db);
if (!exists)
SqliteConnection.CreateFile (db);
// Create connection to the database
var conn = new SqliteConnection("Data Source=" + db);
// Set the structure of the database
if (!exists) {
var commands = new[] {
"CREATE TABLE People (ID TEXT, Name TEXT, Occupation TEXT, isManager BOOLEAN, ManagerID TEXT)"
};
conn.Open ();
foreach (var cmd in commands) {
using (var c = conn.CreateCommand()) {
c.CommandText = cmd;
c.CommandType = CommandType.Text;
c.ExecuteNonQuery ();
}
}
conn.Close ();
// Build list of employees
var Craig = new PersonModel ("0","Craig Dunn", "Documentation Manager");
Craig.AddPerson (new PersonModel ("Amy Burns", "Technical Writer"));
Craig.AddPerson (new PersonModel ("Joel Martinez", "Web & Infrastructure"));
Craig.AddPerson (new PersonModel ("Kevin Mullins", "Technical Writer"));
Craig.AddPerson (new PersonModel ("Mark McLemore", "Technical Writer"));
Craig.AddPerson (new PersonModel ("Tom Opgenorth", "Technical Writer"));
Craig.Create (conn);
var Larry = new PersonModel ("1","Larry O'Brien", "API Documentation Manager");
Larry.AddPerson (new PersonModel ("Mike Norman", "API Documentor"));
Larry.Create (conn);
}
// Return new connection
return conn;
}
Yukarıdaki koda daha yakından bakalım. İlk olarak, yeni veritabanı için bir konum seçeriz (bu örnekte kullanıcının Masaüstü), veritabanının mevcut olup olmadığını görmek ve yoksa veritabanını oluşturun:
var documents = Environment.GetFolderPath (Environment.SpecialFolder.Desktop);
string db = Path.Combine (documents, "People.db3");
// Create the database if it doesn't already exist
bool exists = File.Exists (db);
if (!exists)
SqliteConnection.CreateFile (db);
Ardından, yukarıda oluşturduğum yolu kullanarak veritabanına bağlanmayı sağlarsınız:
var conn = new SqliteConnection("Data Source=" + db);
Ardından veritabanında gerekli SQL tablolarını oluştururuz:
var commands = new[] {
"CREATE TABLE People (ID TEXT, Name TEXT, Occupation TEXT, isManager BOOLEAN, ManagerID TEXT)"
};
conn.Open ();
foreach (var cmd in commands) {
using (var c = conn.CreateCommand()) {
c.CommandText = cmd;
c.CommandType = CommandType.Text;
c.ExecuteNonQuery ();
}
}
conn.Close ();
Son olarak, uygulama ilk kez çalıştırılana veya veritabanı eksikse veritabanı için varsayılan bir kayıt kümesi oluşturmak üzere Veri Modelimizi ( PersonModel ) kullanırsınız:
// Build list of employees
var Craig = new PersonModel ("0","Craig Dunn", "Documentation Manager");
Craig.AddPerson (new PersonModel ("Amy Burns", "Technical Writer"));
Craig.AddPerson (new PersonModel ("Joel Martinez", "Web & Infrastructure"));
Craig.AddPerson (new PersonModel ("Kevin Mullins", "Technical Writer"));
Craig.AddPerson (new PersonModel ("Mark McLemore", "Technical Writer"));
Craig.AddPerson (new PersonModel ("Tom Opgenorth", "Technical Writer"));
Craig.Create (conn);
var Larry = new PersonModel ("1","Larry O'Brien", "API Documentation Manager");
Larry.AddPerson (new PersonModel ("Mike Norman", "API Documentor"));
Larry.Create (conn);
Uygulama başlatıldığında ve Ana Pencereyi açtığında, yukarıda ekley sayfayı kullanarak veritabanıyla bağlantı oluştururuz:
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Get access to database
DatabaseConnection = GetDatabaseConnection ();
}
Bağlı verileri yükleme
Bir SQLite veritabanından bağlı verilere doğrudan erişmek için tüm bileşenler hazır olduğu için, verileri uygulamamızın sağladığı farklı görünümlere yükleyebilirsiniz ve bu veriler kullanıcı arabirimimizde otomatik olarak görüntülenir.
Tek bir kaydı yükleme
Kimliğin olduğu tek bir kaydı yüklemek için aşağıdaki kodu kullanabiliriz:
Person = new PersonModel (Conn, "0");
Tüm kayıtları yükleme
Yönetici olup olmayan tüm insanları yüklemek için aşağıdaki kodu kullanın:
// Load all employees
_conn.Open ();
using (var command = _conn.CreateCommand ()) {
// Create new command
command.CommandText = "SELECT ID FROM [People]";
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Load child and add to collection
var childID = (string)reader [0];
var person = new PersonModel (_conn, childID);
AddPerson (person);
}
}
}
_conn.Close ();
Burada, kişiyi belleğe yüklemek için sınıfı için PersonModel oluşturucusu aşırı yüklemesi kullanıyoruz:
var person = new PersonModel (_conn, childID);
Kişiyi kişi koleksiyonumuza eklemek için Data Bound sınıfını da çağırıyoruz. Bu, kullanıcı arabirimimizin değişikliği tanımasını ve AddPerson (person) görüntülemesini sağlar:
[Export("addObject:")]
public void AddPerson(PersonModel person) {
WillChangeValue ("personModelArray");
isManager = true;
_people.Add (person);
DidChangeValue ("personModelArray");
}
Yalnızca üst düzey kayıtları yükleme
Yalnızca yöneticileri yüklemek için (örneğin, verileri bir Ana Hat Görünümünde görüntülemek için) aşağıdaki kodu kullanıruz:
// Load only managers employees
_conn.Open ();
using (var command = _conn.CreateCommand ()) {
// Create new command
command.CommandText = "SELECT ID FROM [People] WHERE isManager = 1";
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Load child and add to collection
var childID = (string)reader [0];
var person = new PersonModel (_conn, childID);
AddPerson (person);
}
}
}
_conn.Close ();
deyiminde tek gerçek fark SQL (yalnızca yöneticileri yükler) ama aksi takdirde yukarıdaki command.CommandText = "SELECT ID FROM [People] WHERE isManager = 1" bölümle aynı şekilde çalışır.
Veritabanları ve birleşik giriş kutuları
macOS tarafından kullanılabilen Menü Denetimleri (Birleşik Giriş Kutusu gibi) bir iç listeden (Interface Builder'de önceden tanımlanmış veya kod aracılığıyla doldurulabilir) veya kendi özel dış veri kaynağınızı sağlayarak açılan listeyi doldurabilir. Daha fazla ayrıntı için bkz. Menü Denetimi Verilerini Sağlama.
Örnek olarak, yukarıdaki Basit Bağlama örneğini Interface Builder bir Combo Box ekleyin ve adlı bir çıkış kullanarak EmployeeSelector açın:
ÖznitelikLer Denetçisi'ninOtomatik Tamamlamalar ve Veri Kaynağını Kullanır özelliklerini kontrol edin:

Değişikliklerinizi kaydedin ve eşitlemek Mac için Visual Studio geri dön.
Birleşik giriş kutusu verileri sağlama
Ardından, adlı projeye yeni bir sınıf ComboBoxDataSource ekleyin ve aşağıdaki gibi bir görünüme ekleyin:
using System;
using System.Data;
using System.IO;
using Mono.Data.Sqlite;
using Foundation;
using AppKit;
namespace MacDatabase
{
public class ComboBoxDataSource : NSComboBoxDataSource
{
#region Private Variables
private SqliteConnection _conn = null;
private string _tableName = "";
private string _IDField = "ID";
private string _displayField = "";
private nint _recordCount = 0;
#endregion
#region Computed Properties
public SqliteConnection Conn {
get { return _conn; }
set { _conn = value; }
}
public string TableName {
get { return _tableName; }
set {
_tableName = value;
_recordCount = GetRecordCount ();
}
}
public string IDField {
get { return _IDField; }
set {
_IDField = value;
_recordCount = GetRecordCount ();
}
}
public string DisplayField {
get { return _displayField; }
set {
_displayField = value;
_recordCount = GetRecordCount ();
}
}
public nint RecordCount {
get { return _recordCount; }
}
#endregion
#region Constructors
public ComboBoxDataSource (SqliteConnection conn, string tableName, string displayField)
{
// Initialize
this.Conn = conn;
this.TableName = tableName;
this.DisplayField = displayField;
}
public ComboBoxDataSource (SqliteConnection conn, string tableName, string idField, string displayField)
{
// Initialize
this.Conn = conn;
this.TableName = tableName;
this.IDField = idField;
this.DisplayField = displayField;
}
#endregion
#region Private Methods
private nint GetRecordCount ()
{
bool shouldClose = false;
nint count = 0;
// Has a Table, ID and display field been specified?
if (TableName !="" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT count({IDField}) FROM [{TableName}]";
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Read count from query
var result = (long)reader [0];
count = (nint)result;
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return the number of records
return count;
}
#endregion
#region Public Methods
public string IDForIndex (nint index)
{
NSString value = new NSString ("");
bool shouldClose = false;
// Has a Table, ID and display field been specified?
if (TableName != "" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT {IDField} FROM [{TableName}] ORDER BY {DisplayField} ASC LIMIT 1 OFFSET {index}";
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Read the display field from the query
value = new NSString ((string)reader [0]);
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return results
return value;
}
public string ValueForIndex (nint index)
{
NSString value = new NSString ("");
bool shouldClose = false;
// Has a Table, ID and display field been specified?
if (TableName != "" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT {DisplayField} FROM [{TableName}] ORDER BY {DisplayField} ASC LIMIT 1 OFFSET {index}";
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Read the display field from the query
value = new NSString ((string)reader [0]);
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return results
return value;
}
public string IDForValue (string value)
{
NSString result = new NSString ("");
bool shouldClose = false;
// Has a Table, ID and display field been specified?
if (TableName != "" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT {IDField} FROM [{TableName}] WHERE {DisplayField} = @VAL";
// Populate parameters
command.Parameters.AddWithValue ("@VAL", value);
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Read the display field from the query
result = new NSString ((string)reader [0]);
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return results
return result;
}
#endregion
#region Override Methods
public override nint ItemCount (NSComboBox comboBox)
{
return RecordCount;
}
public override NSObject ObjectValueForItem (NSComboBox comboBox, nint index)
{
NSString value = new NSString ("");
bool shouldClose = false;
// Has a Table, ID and display field been specified?
if (TableName != "" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT {DisplayField} FROM [{TableName}] ORDER BY {DisplayField} ASC LIMIT 1 OFFSET {index}";
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Read the display field from the query
value = new NSString((string)reader [0]);
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return results
return value;
}
public override nint IndexOfItem (NSComboBox comboBox, string value)
{
bool shouldClose = false;
bool found = false;
string field = "";
nint index = NSRange.NotFound;
// Has a Table, ID and display field been specified?
if (TableName != "" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT {DisplayField} FROM [{TableName}] ORDER BY {DisplayField} ASC";
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read () && !found) {
// Read the display field from the query
field = (string)reader [0];
++index;
// Is this the value we are searching for?
if (value == field) {
// Yes, exit loop
found = true;
}
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return results
return index;
}
public override string CompletedString (NSComboBox comboBox, string uncompletedString)
{
bool shouldClose = false;
bool found = false;
string field = "";
// Has a Table, ID and display field been specified?
if (TableName != "" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Escape search string
uncompletedString = uncompletedString.Replace ("'", "");
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT {DisplayField} FROM [{TableName}] WHERE {DisplayField} LIKE @VAL";
// Populate parameters
command.Parameters.AddWithValue ("@VAL", uncompletedString + "%");
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Read the display field from the query
field = (string)reader [0];
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return results
return field;
}
#endregion
}
}
Bu örnekte, herhangi bir NSComboBoxDataSource SQLite Veri Kaynağından Birleşik Giriş Kutusu Öğeleri sunan yeni bir oluşturuyoruz. İlk olarak, aşağıdaki özellikleri tanımlariz:
Conn- SQLite veritabanına bir bağlantı alır veya ayarlar.TableName- Tablo adını alır veya ayarlar.IDField- Verilen Tablo için benzersiz kimliği sağlayan alanı alır veya ayarlar.IDvarsayılan değerdir.DisplayField- Açılan listede görüntülenen alanı alır veya ayarlar.RecordCount- Verilen Tablodaki kayıt sayısını alır.
Nesnenin yeni bir örneğini oluşturduğumuz zaman bağlantıyı, tablo adını, isteğe bağlı olarak KIMLIK alanını ve görüntüleme alanını geçirdik:
public ComboBoxDataSource (SqliteConnection conn, string tableName, string displayField)
{
// Initialize
this.Conn = conn;
this.TableName = tableName;
this.DisplayField = displayField;
}
GetRecordCountYöntemi verilen tablodaki kayıt sayısını döndürür:
private nint GetRecordCount ()
{
bool shouldClose = false;
nint count = 0;
// Has a Table, ID and display field been specified?
if (TableName !="" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT count({IDField}) FROM [{TableName}]";
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Read count from query
var result = (long)reader [0];
count = (nint)result;
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return the number of records
return count;
}
TableNameIDField Ya da Özellikler değerinin her değiştirildiği zaman çağrılır DisplayField .
IDForIndexYöntemi, IDField belirtilen açılan liste öğesi dizinindeki kayıt IÇIN benzersiz kimliği () döndürür:
public string IDForIndex (nint index)
{
NSString value = new NSString ("");
bool shouldClose = false;
// Has a Table, ID and display field been specified?
if (TableName != "" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT {IDField} FROM [{TableName}] ORDER BY {DisplayField} ASC LIMIT 1 OFFSET {index}";
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Read the display field from the query
value = new NSString ((string)reader [0]);
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return results
return value;
}
ValueForIndexYöntemi, DisplayField belirtilen açılan liste dizinindeki öğe için değeri () döndürür:
public string ValueForIndex (nint index)
{
NSString value = new NSString ("");
bool shouldClose = false;
// Has a Table, ID and display field been specified?
if (TableName != "" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT {DisplayField} FROM [{TableName}] ORDER BY {DisplayField} ASC LIMIT 1 OFFSET {index}";
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Read the display field from the query
value = new NSString ((string)reader [0]);
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return results
return value;
}
IDForValueYöntemi IDField verilen değer () IÇIN benzersiz kimliği () döndürür DisplayField :
public string IDForValue (string value)
{
NSString result = new NSString ("");
bool shouldClose = false;
// Has a Table, ID and display field been specified?
if (TableName != "" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT {IDField} FROM [{TableName}] WHERE {DisplayField} = @VAL";
// Populate parameters
command.Parameters.AddWithValue ("@VAL", value);
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Read the display field from the query
result = new NSString ((string)reader [0]);
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return results
return result;
}
, ItemCountTableNameIDField Veya özellikleri değiştirildiğinde listedeki öğelerin önceden hesaplanmış sayısını döndürür DisplayField :
public override nint ItemCount (NSComboBox comboBox)
{
return RecordCount;
}
ObjectValueForItemYöntemi, DisplayField belirtilen açılan liste öğesi dizini için () değerini sağlar:
public override NSObject ObjectValueForItem (NSComboBox comboBox, nint index)
{
NSString value = new NSString ("");
bool shouldClose = false;
// Has a Table, ID and display field been specified?
if (TableName != "" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT {DisplayField} FROM [{TableName}] ORDER BY {DisplayField} ASC LIMIT 1 OFFSET {index}";
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Read the display field from the query
value = new NSString((string)reader [0]);
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return results
return value;
}
LIMITOFFSET SQLite komutumuzdaki ve deyimlerini, gerekli olduğumuz bir kayıtla sınırlamak için kullanıyoruz.
IndexOfItemYöntemi verilen değerin () aşağı açılan öğe dizinini döndürür DisplayField :
public override nint IndexOfItem (NSComboBox comboBox, string value)
{
bool shouldClose = false;
bool found = false;
string field = "";
nint index = NSRange.NotFound;
// Has a Table, ID and display field been specified?
if (TableName != "" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT {DisplayField} FROM [{TableName}] ORDER BY {DisplayField} ASC";
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read () && !found) {
// Read the display field from the query
field = (string)reader [0];
++index;
// Is this the value we are searching for?
if (value == field) {
// Yes, exit loop
found = true;
}
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return results
return index;
}
Değer bulunamazsa, NSRange.NotFound değer döndürülür ve açılan listede tüm öğeler seçili değildir.
CompletedStringYöntemi, DisplayField kısmen yazılmış bir girdi için ilk eşleşen değeri () döndürür:
public override string CompletedString (NSComboBox comboBox, string uncompletedString)
{
bool shouldClose = false;
bool found = false;
string field = "";
// Has a Table, ID and display field been specified?
if (TableName != "" && IDField != "" && DisplayField != "") {
// Is the database already open?
if (Conn.State != ConnectionState.Open) {
shouldClose = true;
Conn.Open ();
}
// Escape search string
uncompletedString = uncompletedString.Replace ("'", "");
// Execute query
using (var command = Conn.CreateCommand ()) {
// Create new command
command.CommandText = $"SELECT {DisplayField} FROM [{TableName}] WHERE {DisplayField} LIKE @VAL";
// Populate parameters
command.Parameters.AddWithValue ("@VAL", uncompletedString + "%");
// Get the results from the database
using (var reader = command.ExecuteReader ()) {
while (reader.Read ()) {
// Read the display field from the query
field = (string)reader [0];
}
}
}
// Should we close the connection to the database
if (shouldClose) {
Conn.Close ();
}
}
// Return results
return field;
}
Verileri görüntüleme ve olaylara yanıt verme
Tüm parçaları bir araya getirmek için, öğesini düzenleyin SubviewSimpleBindingController ve aşağıdaki gibi görünür yapın:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.IO;
using Mono.Data.Sqlite;
using Foundation;
using AppKit;
namespace MacDatabase
{
public partial class SubviewSimpleBindingController : AppKit.NSViewController
{
#region Private Variables
private PersonModel _person = new PersonModel();
private SqliteConnection Conn;
#endregion
#region Computed Properties
//strongly typed view accessor
public new SubviewSimpleBinding View {
get {
return (SubviewSimpleBinding)base.View;
}
}
[Export("Person")]
public PersonModel Person {
get {return _person; }
set {
WillChangeValue ("Person");
_person = value;
DidChangeValue ("Person");
}
}
public ComboBoxDataSource DataSource {
get { return EmployeeSelector.DataSource as ComboBoxDataSource; }
}
#endregion
#region Constructors
// Called when created from unmanaged code
public SubviewSimpleBindingController (IntPtr handle) : base (handle)
{
Initialize ();
}
// Called when created directly from a XIB file
[Export ("initWithCoder:")]
public SubviewSimpleBindingController (NSCoder coder) : base (coder)
{
Initialize ();
}
// Call to load from the XIB/NIB file
public SubviewSimpleBindingController (SqliteConnection conn) : base ("SubviewSimpleBinding", NSBundle.MainBundle)
{
// Initialize
this.Conn = conn;
Initialize ();
}
// Shared initialization code
void Initialize ()
{
}
#endregion
#region Private Methods
private void LoadSelectedPerson (string id)
{
// Found?
if (id != "") {
// Yes, load requested record
Person = new PersonModel (Conn, id);
}
}
#endregion
#region Override Methods
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Configure Employee selector dropdown
EmployeeSelector.DataSource = new ComboBoxDataSource (Conn, "People", "Name");
// Wireup events
EmployeeSelector.Changed += (sender, e) => {
// Get ID
var id = DataSource.IDForValue (EmployeeSelector.StringValue);
LoadSelectedPerson (id);
};
EmployeeSelector.SelectionChanged += (sender, e) => {
// Get ID
var id = DataSource.IDForIndex (EmployeeSelector.SelectedIndex);
LoadSelectedPerson (id);
};
// Auto select the first person
EmployeeSelector.StringValue = DataSource.ValueForIndex (0);
Person = new PersonModel (Conn, DataSource.IDForIndex(0));
}
#endregion
}
}
DataSourceÖzelliği ComboBoxDataSource Birleşik giriş kutusuna eklenen (yukarıda oluşturulan) için bir kısayol sağlar.
LoadSelectedPersonYöntemi, belirtilen BENZERSIZ kimlik için kişiyi veritabanından yükler:
private void LoadSelectedPerson (string id)
{
// Found?
if (id != "") {
// Yes, load requested record
Person = new PersonModel (Conn, id);
}
}
AwakeFromNibYöntemin geçersiz kılınması sırasında, ilk olarak özel Birleşik giriş kutusu veri kaynağınıza ait bir örnek ekleyeceğiz:
EmployeeSelector.DataSource = new ComboBoxDataSource (Conn, "People", "Name");
Daha sonra, IDField varsa belirtilen kişiyi sunan ve yükleyen verilerin ilişkili BENZERSIZ kimliğini () bularak, açılan kutunun metin değerini düzenleyerek kullanıcıya yanıt veririz:
EmployeeSelector.Changed += (sender, e) => {
// Get ID
var id = DataSource.IDForValue (EmployeeSelector.StringValue);
LoadSelectedPerson (id);
};
Kullanıcı açılan listeden yeni bir öğe seçerse yeni bir kişi de yükledik:
EmployeeSelector.SelectionChanged += (sender, e) => {
// Get ID
var id = DataSource.IDForIndex (EmployeeSelector.SelectedIndex);
LoadSelectedPerson (id);
};
Son olarak, Birleşik giriş kutusunu ve görünen kişiyi listedeki ilk öğe ile otomatik olarak doldurduk:
// Auto select the first person
EmployeeSelector.StringValue = DataSource.ValueForIndex (0);
Person = new PersonModel (Conn, DataSource.IDForIndex(0));
SQLite.NET ORM
Yukarıda belirtildiği gibi, açık kaynak SQLite.net nesne ilişkisi YÖNETICISI (ORM) kullanılarak, bir SQLite veritabanından veri okumak ve yazmak için gereken kod miktarını önemli ölçüde azaltabiliriz. Bu, anahtar-değer kodlama ve veri bağlamanın bir nesne üzerinde yer aldığı gereksinimlerinden bazıları nedeniyle Veri bağlamada yapılacak en iyi yol olmayabilir.
SQLite.Net web sitesine göre, "SQLite, kendi içinde, sunucusuz, sıfır yapılandırma, işlemsel SQL veritabanı altyapısını uygulayan bir yazılım kitaplığıdır. SQLite, dünyanın en yaygın olarak dağıtılan veritabanı altyapısıdır. SQLite için kaynak kodu genel etki alanında. "
Aşağıdaki bölümlerde, bir tablo görünümü için veri sağlamak üzere SQLite.Net 'in nasıl kullanılacağını göstereceğiz.
SQLite.net NuGet dahil
SQLite.NET, uygulamanıza eklediğiniz NuGet bir paket olarak sunulur. SQLite.NET kullanarak veritabanı desteği ekleyebilmek için önce bu paketi eklememiz gerekiyor.
Paketi eklemek için aşağıdakileri yapın:
Çözüm bölmesipaketler klasörüne sağ tıklayın ve paket Ekle... seçeneğini belirleyin.
SQLite.netSQLite.netgirin ve SQLite-net girişini seçin:Son için paket Ekle düğmesine tıklayın.
Veri modeli oluşturma
Projeye yeni bir sınıf ekleyelim ve çağrısı yapın OccupationModel . Daha sonra, Meslepationmodel. cs dosyasını düzenleyip aşağıdaki gibi görünmesini sağlayın:
using System;
using SQLite;
namespace MacDatabase
{
public class OccupationModel
{
#region Computed Properties
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Name { get; set;}
public string Description { get; set;}
#endregion
#region Constructors
public OccupationModel ()
{
}
public OccupationModel (string name, string description)
{
// Initialize
this.Name = name;
this.Description = description;
}
#endregion
}
}
İlk olarak, SQLite.NET ( using Sqlite ) ' i ekledik, her biri bu kayıt kaydedildiğinde veritabanına yazılacak birkaç özelliği kullanıma sunduk. Birincil anahtar olarak yaptığımız ilk özellik aşağıdaki şekilde otomatik artış olarak ayarlanır:
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
Veritabanı başlatılıyor
Veri modelimizin veritabanına okumayı ve veritabanını yazmayı desteklemek için yaptığı değişikliklerle, veritabanına bir bağlantı açmanız ve ilk çalıştırmada onu başlatması gerekir. Aşağıdaki kodu ekleyelim:
using SQLite;
...
public SQLiteConnection Conn { get; set; }
...
private SQLiteConnection GetDatabaseConnection() {
var documents = Environment.GetFolderPath (Environment.SpecialFolder.Desktop);
string db = Path.Combine (documents, "Occupation.db3");
OccupationModel Occupation;
// Create the database if it doesn't already exist
bool exists = File.Exists (db);
// Create connection to database
var conn = new SQLiteConnection (db);
// Initially populate table?
if (!exists) {
// Yes, build table
conn.CreateTable<OccupationModel> ();
// Add occupations
Occupation = new OccupationModel ("Documentation Manager", "Manages the Documentation Group");
conn.Insert (Occupation);
Occupation = new OccupationModel ("Technical Writer", "Writes technical documentation and sample applications");
conn.Insert (Occupation);
Occupation = new OccupationModel ("Web & Infrastructure", "Creates and maintains the websites that drive documentation");
conn.Insert (Occupation);
Occupation = new OccupationModel ("API Documentation Manager", "Manages the API Documentation Group");
conn.Insert (Occupation);
Occupation = new OccupationModel ("API Documenter", "Creates and maintains API documentation");
conn.Insert (Occupation);
}
return conn;
}
İlk olarak, veritabanı için bir yol (Bu durumda kullanıcının masaüstü) alırız ve veritabanının zaten var olup olmadığını görürsünüz:
var documents = Environment.GetFolderPath (Environment.SpecialFolder.Desktop);
string db = Path.Combine (documents, "Occupation.db3");
OccupationModel Occupation;
// Create the database if it doesn't already exist
bool exists = File.Exists (db);
Daha sonra, yukarıda oluşturduğumuz yolda veritabanıyla bağlantı kuruyoruz:
var conn = new SQLiteConnection (db);
Son olarak, tabloyu oluşturur ve bazı varsayılan kayıtları ekler:
// Yes, build table
conn.CreateTable<OccupationModel> ();
// Add occupations
Occupation = new OccupationModel ("Documentation Manager", "Manages the Documentation Group");
conn.Insert (Occupation);
Occupation = new OccupationModel ("Technical Writer", "Writes technical documentation and sample applications");
conn.Insert (Occupation);
Occupation = new OccupationModel ("Web & Infrastructure", "Creates and maintains the websites that drive documentation");
conn.Insert (Occupation);
Occupation = new OccupationModel ("API Documentation Manager", "Manages the API Documentation Group");
conn.Insert (Occupation);
Occupation = new OccupationModel ("API Documenter", "Creates and maintains API documentation");
conn.Insert (Occupation);
Tablo görünümü ekleme
Örnek kullanım olarak, Xcode 'un arabirim Oluşturucu 'daki Kullanıcı arabirimimize bir tablo görünümü ekleyeceğiz. C# kodu aracılığıyla erişebilmemiz için bu tablo görünümünü bir çıkış () yoluyla kullanıma sunacağız OccupationTable :
Daha sonra, bu tabloyu SQLite.NET veritabanındaki verilerle doldurmak için özel sınıflar ekleyeceğiz.
Tablo veri kaynağı oluşturma
Tablomızda veri sağlamak için özel bir veri kaynağı oluşturalım. İlk olarak, adlı yeni bir sınıf ekleyin TableORMDatasource ve aşağıdaki gibi görünür:
using System;
using AppKit;
using CoreGraphics;
using Foundation;
using System.Collections;
using System.Collections.Generic;
using SQLite;
namespace MacDatabase
{
public class TableORMDatasource : NSTableViewDataSource
{
#region Computed Properties
public List<OccupationModel> Occupations { get; set;} = new List<OccupationModel>();
public SQLiteConnection Conn { get; set; }
#endregion
#region Constructors
public TableORMDatasource (SQLiteConnection conn)
{
// Initialize
this.Conn = conn;
LoadOccupations ();
}
#endregion
#region Public Methods
public void LoadOccupations() {
// Get occupations from database
var query = Conn.Table<OccupationModel> ();
// Copy into table collection
Occupations.Clear ();
foreach (OccupationModel occupation in query) {
Occupations.Add (occupation);
}
}
#endregion
#region Override Methods
public override nint GetRowCount (NSTableView tableView)
{
return Occupations.Count;
}
#endregion
}
}
Daha sonra bu sınıfın bir örneğini oluşturduğumuzda açık SQLite.NET veritabanı bağlantınıza geçireceğiz. LoadOccupationsYöntemi veritabanını sorgular ve bulunan kayıtları belleğe kopyalar ( OccupationModel veri modelimizi kullanarak).
Tablo temsilcisi oluşturma
Gereken son sınıf, SQLite.NET veritabanından yüklediğimiz bilgileri göstermek için özel bir tablo temsilcisidir. Şimdi projemizi yeni bir ekleyelim TableORMDelegate ve aşağıdaki gibi görünmesini sağlayın:
using System;
using AppKit;
using CoreGraphics;
using Foundation;
using System.Collections;
using System.Collections.Generic;
using SQLite;
namespace MacDatabase
{
public class TableORMDelegate : NSTableViewDelegate
{
#region Constants
private const string CellIdentifier = "OccCell";
#endregion
#region Private Variables
private TableORMDatasource DataSource;
#endregion
#region Constructors
public TableORMDelegate (TableORMDatasource dataSource)
{
// Initialize
this.DataSource = dataSource;
}
#endregion
#region Override Methods
public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
{
// This pattern allows you reuse existing views when they are no-longer in use.
// If the returned view is null, you instance up a new view
// If a non-null view is returned, you modify it enough to reflect the new data
NSTextField view = (NSTextField)tableView.MakeView (CellIdentifier, this);
if (view == null) {
view = new NSTextField ();
view.Identifier = CellIdentifier;
view.BackgroundColor = NSColor.Clear;
view.Bordered = false;
view.Selectable = false;
view.Editable = false;
}
// Setup view based on the column selected
switch (tableColumn.Title) {
case "Occupation":
view.StringValue = DataSource.Occupations [(int)row].Name;
break;
case "Description":
view.StringValue = DataSource.Occupations [(int)row].Description;
break;
}
return view;
}
#endregion
}
}
Burada, veri kaynağının Occupations koleksiyonunu (SQLite.net veritabanından yüklediğimiz), tablodaki sütunları yöntem geçersiz kılma yoluyla dolduracak şekilde kullanacağız GetViewForItem .
Tablo dolduruluyor
Tüm parçalar varken, yöntemi geçersiz kılarak ve aşağıdakine benzer şekilde. XIB dosyasından bir şey haline geldiğinde tablomızı dolduralım AwakeFromNib :
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Get database connection
Conn = GetDatabaseConnection ();
// Create the Occupation Table Data Source and populate it
var DataSource = new TableORMDatasource (Conn);
// Populate the Product Table
OccupationTable.DataSource = DataSource;
OccupationTable.Delegate = new TableORMDelegate (DataSource);
}
İlk olarak, SQLite.NET veritabanı 'na erişim sağlıyoruz, zaten mevcut değilse bunları oluşturuyor ve doldurduk. Daha sonra, özel tablo veri kaynağınızın yeni bir örneğini oluşturacağız, veritabanı bağlantımızda geçiş yaptık ve tabloya iliştiriyoruz. Son olarak, özel tablo temsilcimizin yeni bir örneğini oluşturacağız, veri kaynağınızı geçirin ve tabloya ekleyin.
Özet
Bu makale, bir Xamarin. Mac uygulamasındaki SQLite veritabanları ile veri bağlama ve anahtar-değer kodlaması ile çalışma hakkında ayrıntılı bir bakış gerçekleştirmiştir. İlk olarak, Objective-C anahtar-değer kodlama (KVC) ve anahtar-değer gözlemleme (KVO) kullanarak bir C# sınıfını kullanıma sunma konusuna baktık. Ardından, bir KVO uyumlu sınıfı kullanmayı ve verileri Xcode 'un Interface Builder Kullanıcı Arabirimi öğelerine bağlamayı gösterdi. Makale Ayrıca SQLite.NET ORM aracılığıyla SQLite verileriyle çalışmayı ve bu verileri bir tablo görünümünde görüntülemeyi kapsar.
İlişkili Bağlantılar
- MacDatabase (örnek)
- Hello, Mac
- Veri bağlama ve anahtar-değer kodlama
- Standart denetimler
- Tablo görünümleri
- Ana hat görünümleri
- Koleksiyon görünümleri
- Anahtar-değer kodlama Programlama Kılavuzu
- Cocoa bağlamaları programlama konularına giriş
- Cocoa bağlamaları başvurusuna giriş
- NSCollectionView
- macOS ınsan arabirimi yönergeleri


çıkararak
sqlite
Tablo görünümü çıkaran