====== Projekt logiczny ======
==== 1. Projektowanie tabel, kluczy, kluczy obcych, powiązań między tabelami, indeksów, etc. w oparciu o zdefiniowany diagram ERD ====
W naszym projekcie wykorzystaliśmy silnik bazy danych Microsoft SQL Server 2008 Express Edition. Poniżej załączony jest kod odpowiedzialny za generowanie schematu bazy danych w T-SQL.
=== Utworzenie struktury tabel ===
create table [DataObject] (
DataObjectId INT IDENTITY NOT NULL,
Path NVARCHAR(255) null,
OriginalFilename NVARCHAR(255) null,
primary key (DataObjectId)
)
create table [Game] (
GameId INT IDENTITY NOT NULL,
Name NVARCHAR(255) null,
Description NVARCHAR(255) null,
Date DATETIME null,
Resolved BIT null,
PhotoID INT null,
UserID INT null,
primary key (GameId)
)
create table [GameAccessControlList] (
GameAccessControlListId INT IDENTITY NOT NULL,
Permission NVARCHAR(255) null,
UserID INT null,
GameID INT null,
primary key (GameAccessControlListId)
)
create table [Response] (
ResponseId INT IDENTITY NOT NULL,
Date DATETIME null,
Comment NVARCHAR(255) null,
Correctness BIT null,
GameID INT null,
UserID INT null,
PhotoID INT null,
primary key (ResponseId)
)
create table [ResponseAccessControlList] (
ResponseAccessControlListId INT IDENTITY NOT NULL,
Permission NVARCHAR(255) null,
UserID INT null,
ResponseID INT null,
primary key (ResponseAccessControlListId)
)
create table [Role] (
RoleId INT IDENTITY NOT NULL,
Name NVARCHAR(255) null,
primary key (RoleId)
)
create table RolesToUsers (
RoleID INT not null,
UserID INT not null
)
create table [User] (
UserId INT IDENTITY NOT NULL,
Username NVARCHAR(255) null,
Email NVARCHAR(255) null,
primary key (UserId)
)
create table FacebookUser (
UserID INT not null,
FacebookId BIGINT null unique,
primary key (UserID)
)
create table LocalUser (
UserID INT not null,
Password NVARCHAR(255) null,
Username NVARCHAR(255) null unique,
primary key (UserID)
)
=== Utworzenie kluczy obcych ===
alter table [Game]
add constraint FK_Game_Photo
foreign key (PhotoID)
references [DataObject]
alter table [Game]
add constraint FK_Game_User
foreign key (UserID)
references [User]
alter table [GameAccessControlList]
add constraint FK_GameAccessControlList_User
foreign key (UserID)
references [User]
alter table [GameAccessControlList]
add constraint FK_GameAccessControlList_Game
foreign key (GameID)
references [Game]
alter table [Response]
add constraint FK_Response_Game
foreign key (GameID)
references [Game]
alter table [Response]
add constraint FK_Response_User
foreign key (UserID)
references [User]
alter table [Response]
add constraint FK_Response_Photo
foreign key (PhotoID)
references [DataObject]
alter table [ResponseAccessControlList]
add constraint FK_ResponseAccessControlList_User
foreign key (UserID)
references [User]
alter table [ResponseAccessControlList]
add constraint FK_ResponseAccessControlList_Response
foreign key (ResponseID)
references [Response]
alter table RolesToUsers
add constraint FK_Role_User
foreign key (UserID)
references [User]
alter table RolesToUsers
add constraint FK_User_Role
foreign key (RoleID)
references [Role]
alter table FacebookUser
add constraint FK_User
foreign key (UserID)
references [User]
alter table LocalUser
add constraint FK_User2
foreign key (UserID)
references [User]
==== 2. Słownik danych ====
^Nazwa tabeli ^Nazwa pola ^Numer pola ^Wartosc domyslna ^Czy nullowalne ^Typ pola ^
|DataObject |DataObjectId |1 |NULL |NO |int |NULL
|DataObject |OriginalFilename |3 |NULL |YES |nvarchar |255
|DataObject |Path |2 |NULL |YES |nvarchar |255
|FacebookUser |FacebookId |2 |NULL |YES |bigint |NULL
|FacebookUser |User_id |1 |NULL |NO |int |NULL
|Game |Date |4 |NULL |YES |datetime |NULL
|Game |Description |3 |NULL |YES |nvarchar |255
|Game |GameId |1 |NULL |NO |int |NULL
|Game |Name |2 |NULL |YES |nvarchar |255
|Game |Photo_id |5 |NULL |YES |int |NULL
|Game |Resolved |7 |NULL |YES |bit |NULL
|Game |User_id |6 |NULL |YES |int |NULL
|GameAccessControlList |Game_id |4 |NULL |YES |int |NULL
|GameAccessControlList |GameAccessControlListId |1 |NULL |NO |int |NULL
|GameAccessControlList |Permission |2 |NULL |YES |nvarchar |255
|GameAccessControlList |User_id |3 |NULL |YES |int |NULL
|LocalUser |Password |2 |NULL |YES |nvarchar |255
|LocalUser |User_id |1 |NULL |NO |int |NULL
|LocalUser |Username |3 |NULL |YES |nvarchar |255
|Response |Comment |4 |NULL |YES |nvarchar |255
|Response |Correctness |5 |NULL |YES |bit |NULL
|Response |Date |2 |NULL |YES |datetime |NULL
|Response |Game_id |6 |NULL |YES |int |NULL
|Response |Photo_id |9 |NULL |YES |int |NULL
|Response |ResponseId |1 |NULL |NO |int |NULL
|Response |User_id |8 |NULL |YES |int |NULL
|ResponseAccessControlList |Permission |2 |NULL |YES |nvarchar |255
|ResponseAccessControlList |Response_id |4 |NULL |YES |int |NULL
|ResponseAccessControlList |ResponseAccessControlListId |1 |NULL |NO |int |NULL
|ResponseAccessControlList |User_id |3 |NULL |YES |int |NULL
|Role |Name |2 |NULL |YES |nvarchar |255
|Role |RoleId |1 |NULL |NO |int |NULL
|RolesToUsers |Role_id |1 |NULL |NO |int |NULL
|RolesToUsers |User_id |2 |NULL |NO |int |NULL
|User |Email |3 |NULL |YES |nvarchar |255
|User |UserId |1 |NULL |NO |int |NULL
|User |Username |2 |NULL |YES |nvarchar |255
|NULL |NULL |NULL |NULL |NULL |NULL |NULL
==== 3. Analiza zależności funkcyjnych i normalizacja tabel (dekompozycja do 3NF, BCNF, 4NF, 5NF) ====
{{:pl:dydaktyka:ztb:2012:projekty:fotodetektyw:erd2.jpg|}}
1NF - Warunki pierwszej postaci normalnej są spełnione:
* Kaząda relacja opisuje jeden obiekt
* Wartości atrybutów są elementarne
* nie zawiera kolekcji
* posiada klucz główny
* kolejność wierszy może być dowolna
2NF - Wszystkie relacje spełniają pierwszą postać normalną i każda kolumna zależy od klucza głównego.
3NF - Trzecia postać normalna nie jest spełniona. Warunek mówiący o tym, że każda kolumna nienależąca do klucza głównego powinna być od niego bezpośrednio zależna nie jest spełniony przez tabelę RemoteAccessControlList - pole Permission.
==== 4. Projektowanie operacji na danych ====
Nasza aplikacja nie wykorzystuje predefiniowanych operacji na bazie danych. Wszystkie operacja wykonywane są mechanizm ORM - framework nHibernate. Do stworzenia map wykorzystana została nakładka Fluent nHibernate co pozwoliło na zastosowanie konwencji. Poniższy kod automatycznie mapuje wszystkie klasy implementujące interfejs IEntity i stosuje na nich konwencje określające nazwy kluczy.
== Konfiguracja konwencji mapujących ==
var fluentConfig = Fluently.Configure()
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(connectionString))
.Mappings( m=>
m.AutoMappings.Add(
AutoMap.Assemblies(AppDomain.CurrentDomain.GetAssemblies())
.Where(t => t.GetInterfaces().Contains(typeof(IEntity)))
.IncludeBase()
.Conventions.Add()
.Conventions.Add()
.Conventions.Add()
.Conventions.Add(FluentNHibernate.Conventions.Helpers.DefaultLazy.Never())
.Override( x => x.IgnoreProperty(u => u.File))
.Override( x => x.Map(y => y.FacebookId).Unique())
.Override(x => x.Map(y => y.Username).Unique())
.Override(x => x.IgnoreProperty(y => y.ResponsesNum))
.Override(x => x.IgnoreProperty(y => y.CorrectResponsesNum))
.Override(x => x.IgnoreProperty(y => y.GamesNum))
))
.BuildConfiguration();
Ponieważ obiekty encji były również wykorzystywane do transferu danych pomiędzy frontendem a backendem. Domyślnie wyłączony został Lazy Loading. Jedynym przypadkiem kiedy doładowywanie obiektów jest konieczne jest związek pomiędzy Game i User. W tym celu zdefiniowaliśmy dodatkowe kryteria, umożliwiające tzw. Eager Loading
_session.CreateCriteria("Game").SetFetchMode("User", FetchMode.Eager);