 |
Demo_Books is a technology-oriented console application demonstrating the
following basic DataObjects.Net capabilities:
- Working with the set of persistent classes (look Model.cs);
- Multilingual properties;
- [LoadOnDemand] attribute, built-in optimistic locking mechanism, and
immediate/delayed updates (BeginUpdate and EndUpdate methods );
- Queries, including full-text queries (so Microsoft Search is required to run this
sample on the Microsoft SQL Server);
- References and collections.
Model.cs
using System;
using System.Data;
using DataObjects.NET;
using DataObjects.NET.Attributes;
using DataObjects.NET.FullText;
namespace Demo_Books.Model
{
public abstract class DumpableObject: FtObject
{
public virtual void Dump()
{
Console.WriteLine("");
Console.WriteLine("ID: {0}, Type: {1}",ID,Type.Name);
}
}
[IndexAttribute("IX_NSS",new string[] {"Name","Surname","SecondName"}, Unique=true)]
public abstract class Person: DumpableObject
{
[Length(64)]
[Collatable]
[Indexed]
public abstract string Name {get; set;}
[Length(64)]
[Collatable]
[Indexed]
public abstract string SecondName {get; set;}
[Length(64)]
[Collatable]
[Indexed]
public abstract string Surname {get; set;}
public virtual string FullName {
get {
return Name+" "+SecondName+" "+Surname;
}
}
[Indexed]
[Nullable]
// No DateTime support in Trial, so date is string
public abstract string DOB {get; set;}
[Translatable]
[SqlType(SqlType.Text)]
[LoadOnDemand]
public abstract string Info {get; set;}
public override string ProduceFtData(Culture culture) {
return
"\n "+FullName+
((GetProperty("DOB")!=null) ? "\n DOB: "+DOB : "") +
"\n "+GetProperty("Info",culture);
}
public override void Dump()
{
base.Dump();
Console.WriteLine("FullName: {0}",FullName);
Console.WriteLine("DOB: {0}",(this["DOB"]==null)?"null":DOB.ToString());
foreach (Culture c in Domain.Cultures)
Console.WriteLine("Info-{0}: {1}",c.Name,this["Info",c]);
}
}
public abstract class Author: Person
{
[Indexed]
public abstract Account Account {get; set;}
[Translatable]
[SqlType(SqlType.Text)]
[LoadOnDemand]
public abstract string Resume {get; set;}
[Contained]
[ItemType(typeof(Book))]
[PairTo(typeof(Book),"Author")]
public abstract DataObjectCollection Books {get;}
public override string ProduceFtData(Culture culture) {
return
base.ProduceFtData(culture) +
"\n Book count: "+Books.Count +
((Account!=null)?
("\n Account: "+Account.ProduceFtData(culture)) : "") +
"\n "+GetProperty("Resume",culture);
}
public override void Dump()
{
base.Dump();
try {
Console.WriteLine("Account: {0} (bank {1})",this.Account.Number,this.Account.Bank.Title);
} catch (Exception) {};
foreach (Culture c in Domain.Cultures)
Console.WriteLine("Resume-{0}: {1}",c.Name,this["Resume",c]);
Console.WriteLine("Book count: {0}",Books.Count);
}
}
public abstract class Book: DumpableObject
{
[Indexed(Unique=true)]
public abstract string ISBN {get; set;}
[Collatable]
[Indexed]
public abstract string Title {get; set;}
[Translatable]
[LoadOnDemand]
[Indexed]
public abstract string Description {get; set;}
[Indexed]
public abstract Author Author {get; set;}
public override string ProduceFtData(Culture culture) {
return
"\n ISBN: "+ISBN +
"\n Title: "+Title +
((Author!=null) ?
("\n Author: "+this.Author.ProduceFtData(culture)) : "") +
"\n "+GetProperty("Description",culture);
}
public override void Dump()
{
base.Dump();
Console.WriteLine("ISBN: {0}",ISBN);
Console.WriteLine("Title: {0}",Title);
Console.WriteLine("Author: {0}",Author==null?"null":Author.FullName);
foreach (Culture c in Domain.Cultures)
Console.WriteLine("Description-{0}: {1}",c.Name,this["Description",c]);
}
}
public abstract class Account: DumpableObject
{
[Indexed(Unique=true)]
public abstract string Title {get; set;}
[Indexed]
public abstract Bank Bank {get; set;}
[Indexed]
public abstract long Number {get; set;}
[Nullable]
[LoadOnDemand]
public abstract byte[] SecretInfo {get; set;}
protected override void OnCreate()
{
throw new InvalidOperationException("This constructor can't be used with this type!");
}
// It's upper caller always requires a transaction, so
// TransactionMode.Disabled is appropriate here.
[Transactional(TransactionMode.Disabled)]
protected virtual void OnCreate(string title)
{
Title = title;
base.OnCreate();
}
protected override void OnCreateDeserializable()
{
// We should guarant uniquenes of initial Title
// value, because two or more instance with empty
// Title can be persisted during the deserialization,
// that will lead to violation of 'unique' constraint.
// An actual Title value will be set during the
// deserialization.
Title = Guid.NewGuid().ToString();
base.OnCreateDeserializable();
}
protected override void OnSetProperty(string name, Culture culture, object value)
{
if (name=="Title" && (value==null || ((string)value)==""))
throw new InvalidOperationException("Title shouldn't be empty.");
}
public override string ProduceFtData(Culture culture)
{
return
"\n Title: "+Title +
((Bank!=null)?
("\n Bank: "+Bank.Title) : "") +
"\n N: "+Number.ToString();
}
public override void Dump()
{
base.Dump();
try {
Console.WriteLine("Title: {0}",Title);
Console.WriteLine("Number: {0}",Number);
Console.WriteLine("Bank: {0}",Bank.Title);
} catch (Exception) {};
}
}
public abstract class Company: DumpableObject
{
[Collatable]
[Indexed]
public abstract string Title {get; set;}
[Collatable]
[Indexed]
public abstract string Address {get; set;}
[Indexed]
// No DateTime support in Trial, so date is string
public abstract string RegistrationDate {get; set;}
[Nullable]
[Indexed]
public abstract Account Account {get; set;}
[Translatable]
[SqlType(SqlType.Text)]
[LoadOnDemand]
public abstract string Info {get; set;}
public override string ProduceFtData(Culture culture) {
return
"\n Title: "+Title+
"\n Address: "+Address+
"\n Registeration date: "+RegistrationDate.ToString(culture.Info) +
((Account!=null) ?
("\n Account: "+Account.ProduceFtData(culture)) : "") +
"\n "+GetProperty("Info",culture);
}
public override void Dump()
{
base.Dump();
Console.WriteLine("Title: {0}",Title);
Console.WriteLine("Address: {0}",Address);
Console.WriteLine("Reg.Date: {0}",RegistrationDate);
try {
Console.WriteLine("Account: {0} (bank {1})",this.Account.Number,this.Account.Bank.Title);
} catch (Exception) {};
foreach (Culture c in Domain.Cultures)
Console.WriteLine("Info-{0}: {1}",c.Name,this["Info",c]);
}
}
public abstract class Bank: Company
{
[Contained]
[ItemType(typeof(Account))]
[PairTo(typeof(Account),"Bank")]
public abstract DataObjectCollection Accounts {get;}
public override string ProduceFtData(Culture culture) {
return
base.ProduceFtData(culture) +
"\n Account count: "+Accounts.Count;
}
public override void Dump()
{
base.Dump();
Console.WriteLine("Account count: {0}",Accounts.Count);
}
}
}
Books.cs
using System;
using System.IO;
using System.Text;
using System.Threading;
using System.Globalization;
using System.Data;
using System.Data.SqlClient;
using DataObjects.NET;
using DataObjects.NET.FullText;
using DataObjects.NET.RuntimeServices;
using Demo_Books.Model;
namespace Demo_Books
{
class Books
{
static Domain domain;
static string connectionUrl = "";
[STAThread]
static void Main(string[] args)
{
Console.WriteLine("DataObjects.Net: Books demo\n");
SelectDatabase();
CreateDomain();
CreateData();
DumpData();
ModifyData();
DumpData();
FullTextQuery();
Console.Write("\nPress Enter to close... ");
Console.ReadLine();
}
static void SelectDatabase()
{
while (connectionUrl=="") {
Console.Write("Select database server to use:\n" +
"1) Microsoft SQL Server\n" +
"2) Oracle\n" +
"3) Native Oracle\n" +
"4) SAP DB\n" +
"> ");
string dbType = Console.ReadLine();
switch (dbType) {
case "1":
Console.WriteLine("Selected: Microsoft SQL Server.");
connectionUrl = "mssql://localhost/DataObjectsDotNetDemos";
break;
case "2":
Console.WriteLine("Selected: Oracle.");
connectionUrl = "oracle://admin:admin@localhost/Demos";
break;
case "3":
Console.WriteLine("Selected: Native Oracle.");
connectionUrl = "nativeoracle://admin:admin@localhost/Demos";
break;
case "4":
Console.WriteLine("Selected: SAP DB.");
connectionUrl = "sapdb://admin:admin@localhost/Demos";
break;
default:
Console.WriteLine("Illegal selection.");
break;
}
}
}
static void CreateDomain()
{
Console.WriteLine("Reading product key...");
string productKeyFile = @"..\..\..\..\ProductKey.txt";
string productKey = "";
if (File.Exists(productKeyFile))
using (StreamReader sr = new StreamReader(productKeyFile)) {
productKey = sr.ReadToEnd().Trim();
}
Console.WriteLine("");
Console.WriteLine("Building domain...");
domain = new Domain(connectionUrl, productKey);
Console.WriteLine("Connection URL: {0}",domain.ConnectionURL);
Console.WriteLine("Driver: {0}",domain.Driver.Info.Description);
domain.RegisterCulture(new Culture("En","U.S. English", new CultureInfo("en-us",false)));
domain.RegisterCulture(new Culture("Ru","Russian", new CultureInfo("ru-ru",false)));
domain.Cultures["En"].Default = true;
domain.RegisterTypes("Demo_Books.Model");
#if DEBUG
domain.DebugInfoOutputFolder = @"C:\Debug";
#endif
domain.Build(DomainUpdateMode.Recreate);
Console.WriteLine(" OK");
}
static void CreateData()
{
Console.WriteLine("Creating data...");
StringBuilder sbBigStringEn = new StringBuilder();
for (int i = 0; i<5; i++)
sbBigStringEn.Append("About author... ");
StringBuilder sbBigStringRu = new StringBuilder();
for (int i = 0; i<5; i++)
sbBigStringRu.Append("Об авторе... ");
Culture cEn = domain.Cultures["En"];
Culture cRu = domain.Cultures["Ru"];
using (Session s = domain.CreateSession()) {
s.BeginTransaction();
// Authors
Author a1 = (Author)s.CreateObject(typeof(Author));
a1.Name = "Alex";
a1.Surname = "Yakunin";
a1.Info = "DataObjects.Net, " + sbBigStringEn.ToString();
s.Culture = cRu;
a1.Info = sbBigStringRu.ToString();
s.Culture = cEn;
Author a2 = (Author)s.CreateObject(typeof(Author));
a2.Name = "Dmitriy";
a2.Surname = "Voronov";
a2.Info = sbBigStringEn.ToString();
s.Culture = cRu;
a2.Info = sbBigStringRu.ToString();
s.Culture = cEn;
Author a3 = (Author)s.CreateObject(typeof(Author));
a3.Name = "Alex";
a3.Surname = "Chernikh";
a3.Info = sbBigStringEn.ToString();
s.Culture = cRu;
a3.Info = sbBigStringRu.ToString();
s.Culture = cEn;
// Books
Book bk1 = (Book)s.CreateObject(typeof(Book));
bk1.ISBN = "AABBCC";
bk1.Title = "DataObjects.Net Internals";
bk1.Description = "DataObjects.Net is... " + sbBigStringEn.ToString();
s.Culture = cRu;
bk1.Description = "DataObjects.Net есть... " + sbBigStringEn.ToString();
s.Culture = cEn;
bk1.Author = a1;
Book bk2 = (Book)s.CreateObject(typeof(Book));
bk2.ISBN = "BBCCDD";
bk2.Title = "DataObjects.Net Manual";
bk2.Description = "DataObjects.Net is... " + sbBigStringEn.ToString();
s.Culture = cRu;
bk2.Description = "DataObjects.Net есть... " + sbBigStringEn.ToString();
s.Culture = cEn;
bk2.Author = a2;
Book bk3 = (Book)s.CreateObject(typeof(Book));
bk3.ISBN = "1DHF23";
bk3.Title = "DataObjects.Net at Glance";
bk3.Description = "DataObjects.Net is... " + sbBigStringEn.ToString();
s.Culture = cRu;
bk3.Description = "DataObjects.Net есть... " + sbBigStringEn.ToString();
s.Culture = cEn;
bk3.Author = a1;
// Persons
Person p1 = (Person)s.CreateObject(typeof(Person));
p1.Name = "Vladimir";
p1.Surname = "Putin";
p1.Info = "Putin "+sbBigStringEn.ToString();
s.Culture = cRu;
p1.Info = "Путин "+sbBigStringRu.ToString();
s.Culture = cEn;
// Banks
Bank b1 = (Bank)s.CreateObject(typeof(Bank));
b1.Title = "Bank of Russia";
Bank b2 = (Bank)s.CreateObject(typeof(Bank));
b2.Title = "Other Bank";
// Accounts
Account ac1= (Account)s.CreateObject(typeof(Account), "Account 1");
ac1.Number = 10102020;
ac1.Bank = b1;
ac1.SecretInfo = new byte[] {1,2,3,4};
a1.Account = ac1;
a2.Account = ac1;
Account ac2= (Account)s.CreateObject(typeof(Account), "Account 2");
ac2.Number = 10103030;
ac2.Bank = b1;
ac2.SecretInfo = new byte[] {2,3,4};
a3.Account = ac2;
Account ac3= (Account)s.CreateObject(typeof(Account), "Account 3");
ac3.Number = 20303030;
ac3.Bank = b2;
s.Commit();
}
Console.WriteLine(" OK");
}
static void ModifyData()
{
Console.WriteLine("Modifying data...");
using (Session s = domain.CreateSession()) {
s.BeginTransaction();
Query q = new Query(s,"Select Book instances");
DataObject[] qr = q.ExecuteArray();
foreach (Book b in qr) {
b.Title += " - Second edition";
}
s.Commit();
}
Console.WriteLine(" Transaction rollback");
using (Session s = domain.CreateSession()) {
s.BeginTransaction(IsolationLevel.Serializable);
SqlQuery q = new SqlQuery(s,typeof(Book));
DataObject[] qr = q.ExecuteArray();
foreach (Book b in qr) {
b.Title += " - Third edition";
}
s.Rollback();
}
Console.WriteLine(" OK");
}
static void FullTextQuery()
{
Console.WriteLine("Full-text search...");
if (!domain.ExtractedDatabaseModel.ExtractedInfo.FullTextIndexingRunning) {
Console.WriteLine(" Full-text search\\indexing isn't available.");
Console.WriteLine(" LikeExpression mode (slow) will be used.");
}
// Let's update full-text data immediately!
using (Session s = domain.CreateSession()) {
FtIndexer ftIndexer = (FtIndexer)s.CreateService(typeof(FtIndexer), 1000000);
ftIndexer.Execute();
}
string searchString;
Culture searchCulture = null;
do {
Console.Write(" Type the text to search: ");
searchString = Console.ReadLine();
Console.Write(" Select the culture to search in (1-En, 2-Ru): ");
switch (Console.ReadLine()) {
case "1":
searchCulture = domain.Cultures["En"];
break;
case "2":
searchCulture = domain.Cultures["Ru"];
break;
}
} while (searchString.Trim()=="" || searchCulture==null);
Console.WriteLine(" Searching for \"{0}\":", searchString);
using (Session s = domain.CreateSession()) {
DataObject[] result;
if (domain.ExtractedDatabaseModel.ExtractedInfo.FullTextIndexingRunning)
result = s.CreateQuery(
"Select DumpableObject instances " +
"textsearch freetext "+s.Utils.QuoteString(searchString)+" " +
"within "+s.Utils.QuoteString(searchCulture.Name)+" culture " +
"order by {FullTextRank} desc").ExecuteArray();
else
result = s.CreateQuery(
"Select DumpableObject instances " +
"textsearch likeExpression "+s.Utils.QuoteString("%"+searchString+"%")+" " +
"within "+s.Utils.QuoteString(searchCulture.Name)+" culture " +
"order by {ID}").ExecuteArray();
foreach (DumpableObject o in result)
o.Dump();
}
Console.WriteLine(" OK");
}
static void DumpData()
{
Console.WriteLine("\nDatabase dump:");
using (Session s = domain.CreateSession()) {
s.BeginTransaction();
Query q = new Query(s,"Select DumpableObject instances");
DataObject[] qr = q.ExecuteArray();
foreach (DumpableObject o in qr)
o.Dump();
s.Commit();
}
Console.WriteLine("");
}
}
}
|
|