Relace, vlastnosti navigace a cizí klíče
Tento článek obsahuje přehled toho, jak Entity Framework spravuje vztahy mezi entitami. Poskytuje také pokyny k mapování a manipulaci s relacemi.
Relace v EF
V relačních databázích se relace (označované také jako asociace) mezi tabulkami definují prostřednictvím cizích klíčů. Cizí klíč (FK) je sloupec nebo kombinace sloupců, které slouží k vytvoření a vynucení propojení mezi daty ve dvou tabulkách. Obecně existují tři typy relací: 1:1, 1:N a M:N. V relaci 1:N je cizí klíč definován v tabulce, která představuje mnoho konce relace. Relace M:N zahrnuje definování třetí tabulky (označované jako tabulka spojení nebo spojení), jejíž primární klíč se skládá z cizích klíčů z obou souvisejících tabulek. V relaci 1:1 primární klíč funguje navíc jako cizí klíč a pro žádnou tabulku neexistuje žádný samostatný sloupec cizího klíče.
Následující obrázek ukazuje dvě tabulky, které se účastní relace 1:N. Tabulka Course je závislá tabulka, protože obsahuje sloupec Id oddělení , který ji propojuje s tabulkou Oddělení .
V Entity Frameworku může entita souviset s jinými entitami prostřednictvím přidružení nebo relace. Každá relace obsahuje dva konce, které popisují typ entity a násobnost typu (jedna, nula nebo jedna nebo mnoho) pro tyto dvě entity v dané relaci. Relace může být řízena referenčním omezením, které popisuje, který konec relace je hlavní rolí a která je závislá role.
Navigační vlastnosti poskytují způsob, jak procházet přidružení mezi dvěma typy entit. Každý objekt může mít navigační vlastnost pro každou relaci, do které se účastní. Navigační vlastnosti umožňují procházet a spravovat relace v obou směrech a vracet buď objekt odkazu (pokud je násobnost jedna nebo nula nebo jedna), nebo kolekci (pokud je násobnost mnoho). Můžete také zvolit jednosměrnou navigaci, v takovém případě definujete navigační vlastnost pouze u jednoho z typů, které se účastní relace, a ne na obou.
Do modelu, který se mapuje na cizí klíče v databázi, se doporučuje zahrnout vlastnosti. Při zahrnutí vlastností cizího klíče můžete vytvořit nebo změnit relaci úpravou hodnoty cizího klíče u závislého objektu. Tento druh asociace se nazývá přidružení cizího klíče. Použití cizích klíčů je ještě důležitější při práci s odpojenými entitami. Všimněte si, že při práci s 1:1 nebo 1:0. 1 relace, neexistuje žádný samostatný sloupec cizího klíče, vlastnost primárního klíče funguje jako cizí klíč a je vždy zahrnuta v modelu.
Pokud sloupce cizího klíče nejsou součástí modelu, informace o přidružení se spravují jako nezávislý objekt. Relace se sledují prostřednictvím odkazů na objekt místo vlastností cizího klíče. Tento typ přidružení se nazývá nezávislé přidružení. Nejběžnější způsob, jak upravit nezávislé přidružení, je upravit navigační vlastnosti, které jsou generovány pro každou entitu, která se účastní přidružení.
V modelu můžete použít jeden nebo oba typy přidružení. Pokud ale máte čistou relaci M:N, která je propojená tabulkou spojení, která obsahuje pouze cizí klíče, ef použije nezávislé přidružení ke správě takové relace M:N.
Následující obrázek znázorňuje koncepční model, který byl vytvořen pomocí Návrháře entity Framework. Model obsahuje dvě entity, které se účastní relace 1:N. Obě entity mají navigační vlastnosti. Kurz je závislá entita a má definovanou vlastnost cizího klíče DepartmentID .
Následující fragment kódu ukazuje stejný model, který byl vytvořen pomocí Code First.
public class Course
{
public int CourseID { get; set; }
public string Title { get; set; }
public int Credits { get; set; }
public int DepartmentID { get; set; }
public virtual Department Department { get; set; }
}
public class Department
{
public Department()
{
this.Courses = new HashSet<Course>();
}
public int DepartmentID { get; set; }
public string Name { get; set; }
public decimal Budget { get; set; }
public DateTime StartDate { get; set; }
public int? Administrator {get ; set; }
public virtual ICollection<Course> Courses { get; set; }
}
Konfigurace nebo mapování relací
Zbývající část této stránky popisuje, jak přistupovat k datům pomocí relací a manipulovat s nimi. Informace o nastavení relací v modelu najdete na následujících stránkách.
- Informace o konfiguraci relací v code First najdete v tématu Datové poznámky a rozhraní FLUENT API – Relace.
- Pokud chcete nakonfigurovat relace pomocí Návrháře entity Framework, přečtěte si téma Relace s ef Designerem.
Vytváření a úpravy relací
Při přidružení cizího klíče při změně relace stav závislého objektu EntityState.Unchanged
se změní na EntityState.Modified
. Při nezávislé relaci změna relace neaktualizuje stav závislého objektu.
Následující příklady ukazují, jak pomocí vlastností cizího klíče a navigačních vlastností přidružit související objekty. S přidruženími cizích klíčů můžete použít metodu ke změně, vytvoření nebo úpravě relací. U nezávislých přidružení nelze použít vlastnost cizího klíče.
Přiřazením nové hodnoty k vlastnosti cizího klíče, jako v následujícím příkladu.
course.DepartmentID = newCourse.DepartmentID;
Následující kód odebere relaci nastavením cizího klíče na hodnotu null. Všimněte si, že vlastnost cizího klíče musí být nullable.
course.DepartmentID = null;
Poznámka
Pokud je odkaz v přidaném stavu (v tomto příkladu objektu kurzu), vlastnost navigace odkazu nebude synchronizována s klíčovými hodnotami nového objektu, dokud se nevolá SaveChanges. K synchronizaci nedojde, protože kontext objektu neobsahuje trvalé klíče pro přidané objekty, dokud nebudou uloženy. Pokud musíte mít nové objekty plně synchronizované, jakmile nastavíte relaci, použijte jednu z následujících metod.*
Přiřazením nového objektu k navigační vlastnosti. Následující kód vytvoří vztah mezi kurzem a znakem
department
. Pokud jsou objekty připojeny k kontextu,course
je také přidán dodepartment.Courses
kolekce a odpovídající vlastnost cizího klíče objektucourse
je nastavena na hodnotu vlastnosti klíče oddělení.course.Department = department;
Chcete-li odstranit relaci, nastavte navigační vlastnost na
null
hodnotu . Pokud pracujete s Entity Frameworkem, který je založený na rozhraní .NET 4.0, je potřeba před nastavením na hodnotu null načíst související konec. Příklad:context.Entry(course).Reference(c => c.Department).Load(); course.Department = null;
Počínaje entity Framework 5.0, která je založená na rozhraní .NET 4.5, můžete nastavit relaci na hodnotu null bez načtení souvisejícího konce. Aktuální hodnotu můžete také nastavit na hodnotu null pomocí následující metody.
context.Entry(course).Reference(c => c.Department).CurrentValue = null;
Odstraněním nebo přidáním objektu v kolekci entit Do kolekce můžete například přidat objekt typu
Course
department.Courses
. Tato operace vytvoří vztah mezi konkrétním kurzem a konkrétnímdepartment
. Pokud jsou objekty připojeny k kontextu, odkaz oddělení a vlastnost cizího klíče objektu kurzu bude nastavena na odpovídajícídepartment
.department.Courses.Add(newCourse);
ChangeRelationshipState
Pomocí metody změnit stav zadané relace mezi dvěma objekty entity. Tato metoda se nejčastěji používá při práci s N-vrstvými aplikacemi a nezávislým přidružením (nedá se použít s přidružením cizího klíče). Chcete-li použít tuto metodu, musíte rozevírací seznam ,ObjectContext
jak je znázorněno v následujícím příkladu.
V následujícím příkladu existuje vztah M:N mezi instruktory a kurzy. ZavolánímChangeRelationshipState
metody a předáním parametruEntityState.Added
získáteSchoolContext
informace o přidání relace mezi těmito dvěma objekty:((IObjectContextAdapter)context).ObjectContext. ObjectStateManager. ChangeRelationshipState(course, instructor, c => c.Instructor, EntityState.Added);
Upozorňujeme, že pokud aktualizujete relaci (nejen přidáváte), musíte po přidání nové relace odstranit starou relaci:
((IObjectContextAdapter)context).ObjectContext. ObjectStateManager. ChangeRelationshipState(course, oldInstructor, c => c.Instructor, EntityState.Deleted);
Synchronizace změn mezi cizími klíči a vlastnostmi navigace
Když změníte vztah objektů připojených k kontextu pomocí jedné z metod popsaných výše, Entity Framework musí udržovat cizí klíče, odkazy a kolekce synchronizované. Entity Framework automaticky spravuje tuto synchronizaci (označovanou také jako oprava relací) pro entity POCO s proxy servery. Další informace naleznete v tématu Práce s proxy servery.
Pokud používáte entity POCO bez proxy, musíte se ujistit, že DetectChanges metoda je volána k synchronizaci souvisejících objektů v kontextu. Všimněte si, že následující rozhraní API automaticky aktivují volání DetectChanges .
DbSet.Add
DbSet.AddRange
DbSet.Remove
DbSet.RemoveRange
DbSet.Find
DbSet.Local
DbContext.SaveChanges
DbSet.Attach
DbContext.GetValidationErrors
DbContext.Entry
DbChangeTracker.Entries
- Spuštění dotazu LINQ na
DbSet
Načítání souvisejících objektů
V Entity Frameworku obvykle používáte navigační vlastnosti k načtení entit, které souvisejí s vrácenou entitou definovaným přidružením. Další informace naleznete v tématu Načítání souvisejících objektů.
Poznámka
Při přidružování cizího klíče při načtení souvisejícího konce závislého objektu se související objekt načte na základě hodnoty cizího klíče závislého, který je aktuálně v paměti:
// Get the course where currently DepartmentID = 2.
Course course = context.Courses.First(c => c.DepartmentID == 2);
// Use DepartmentID foreign key property
// to change the association.
course.DepartmentID = 3;
// Load the related Department where DepartmentID = 3
context.Entry(course).Reference(c => c.Department).Load();
V nezávislém přidružení je související konec závislého objektu dotazován na základě hodnoty cizího klíče, která je aktuálně v databázi. Pokud však byla relace změněna a referenční vlastnost závislého objektu odkazuje na jiný objekt objektu, který je načten v kontextu objektu, Entity Framework se pokusí vytvořit relaci, jak je definována v klientovi.
Správa souběžnosti
V cizím i nezávislém přidružení jsou kontroly souběžnosti založené na klíčích entit a dalších vlastnostech entity, které jsou definovány v modelu. Pokud k vytvoření modelu použijete EF Designer, nastavte ConcurrencyMode
atribut na pevný , aby bylo možné určit, že vlastnost má být zkontrolována pro souběžnost. Při použití Code First k definování modelu použijte poznámku ConcurrencyCheck
k vlastnostem, které chcete zkontrolovat pro souběžnost. Při práci s Code First můžete také použít poznámku TimeStamp
k určení, že vlastnost má být kontrolována pro souběžnost. V dané třídě můžete mít pouze jednu vlastnost časového razítka. Code First mapuje tuto vlastnost na pole bez hodnoty null v databázi.
Při práci s entitami, které se účastní kontroly souběžnosti a řešení, doporučujeme vždy používat přidružení cizího klíče.
Další informace najdete v tématu Zpracování konfliktů souběžnosti.
Práce s překrývajícími se klíči
Překrývající se klíče jsou složené klíče, ve kterých jsou některé vlastnosti v klíči také součástí jiného klíče v entitě. V nezávislém přidružení nelze mít překrývající se klíč. Pokud chcete změnit přidružení cizího klíče, které obsahuje překrývající se klíče, doporučujeme místo použití odkazů na objekt změnit hodnoty cizího klíče.