Entity Framework FAQ: Mapping and Modeling (ru-RU)
[[articles:Entity Framework FAQ (ru-RU)|Содержание EF FAQ]]
Каким образом я могу сопоставить хранимую процедуру?
EF поддерживает сопоставление хранимых процедур для всех четырех CRUD (Create, Read, Update, and Delete) операций. Для получения более подробной информации и пример того, как получать сущности используя хранимые процедуры посмотрите следующие ссылки:
- How to Map Stored Procedures using the ADO.NET Entity Framework
- Как определить модель с помощью хранимой процедуры (платформа Entity Framework)
- Как выполнить запрос с использованием хранимой процедуры, имеющей входные и выходные параметры (платформа Entity Framework)
Каким образом можно сопоставить сущности "только для чтения"? Как можно использовать Defining QueryViews в файлах сопоставления?
Для получения доступных только для чтения сущностей используйте Defining Query. Посмотрите Mapping Read-only Entities и Элемент QueryView (язык MSL) для получения более полной информации.
Каким образом я могу изменить DDL скрипты, которые создаются на основе модели при разработке "модель сначала" (model first)?
Действительно, когда вы создаете DDL скрипты на основе модели, у вас может возникнуть необходимость настроить создаваемый SQL. Например, у вас есть поле с типом binary в модели которое вы хотите отражать в timestamp или rowversion (начиная с SQL Server 2008 необходимо использовать rowversion вместо timestamp ), сейчас вы не можете сделать это в дизайнере. Вы можете настроить шаблон T4 который создаст нужный вам DDL скрипт следующим образом:
1. Добавьте структурную аннотацию в файл CSDL, объявив новое пространство имен и затем добавив с него новый элемент:
<Schema xmlns=" http://schemas.microsoft.com/ado/2008/09/edm"
...
xmlns:my="http://tempuri.org/DatabaseTypes">
<Property Type="Binary" Name="TimeStamp" Nullable="false">
<my:databasetype edmx:CopyToSSDL="true">TIMESTAMP</my:databasetype>
</Property>
Для получения более подробной информации посмотрите следующую статью http://blogs.msdn.com/b/efdesign/archive/2008/08/12/structural-annotations-one-pager.aspx.
CopyToSSDL указывае��, что в процессе генерации нужно скопировать указанное свойство в SSDL.
- Сделайте копию файла SSDLToSQL10.tt, расположенного в директории `%localappdata%\Microsoft\AppId]\10.0\Extensions\Microsoft\Entity Framework Tools\DBGen` и поместите в эту или другую папку. Обратите внимание, что не рекомендуется изменять оригинальный SSDLToSQL10.tt.
- Измените копию .tt файла таким образом, чтобы процесс создания DDL скрипта использовал описанную выше аннотацию для создания типа в БД, вместо логики предлагаемой по умолчанию.
Для этого найдите следующий код в файле с расширением .tt:
[<#=Id(prop.Name)#>] <#=prop.ToStoreType()#>
<#=WriteIdentity(prop, targetVersion)#>
<#=WriteNullable(prop.Nullable)#>
<#=(p < entitySet.ElementType.Properties.Count - 1) ? "," : ""#>
И замените его кодом, который считывает аннотацию (если она есть) и использует ее значение вместо предлагаемого по умолчанию в типа в базе данных:
[<#=Id(prop.Name)#>]
<# if (prop.MetadataProperties.Contains("http://tempuri.org/DatabaseTypes:databasetype"))
{
MetadataProperty annotationProperty = prop.MetadataProperties[ "http://tempuri.org/DatabaseTypes:databasetype"];
XElement e = XElement.Parse(annotationProperty.Value.ToString());
string value = e.Value.Trim();
#> <#=value#> <#
} else {
#> <#=prop.ToStoreType()#> <# }
#> <#=WriteIdentity(prop, targetVersion)
#> <#=WriteNullable(prop.Nullable)
#> <#=(p < entitySet.ElementType.Properties.Count - 1) ? "," : ""
#>
Замечание: Чтобы заставить приведенный код работать нужно добавить несколько сборок и пространств имен:
<#@ assembly name="System.Xml.Linq" #>
<#@ assembly name="System.Xml" #>
<#@ import namespace="System.Xml.Linq" #>
<#@ import namespace="System.Xml" #>
- Укажите новое имя .tt файла, чтобы Create Database Wizard использовал новый шаблон при генерации DDL из SSDL. Чтобы сделать это, щелкните правой кнопкой на поверхности Entity Designer’а и установите новое значение свойства DDL Generation Template указав путь к созданному выше файлу с расширением .tt. Для более подробной информации смотрите Как настроить создание базы данных (мастер создания базы данных).
Почему возникает ошибка "Error 2062: no mapping between entity set and association set?"
Эта ошибка может возникать до тех пор пока вы не сгенерировали таблицу на основе модели при разработке “Модель сначала”. Модель не может быть проверена до тех пор, пока все объекты в ней не сопоставляются с таблицами в базе данных. После того, как вы создадите БД на основе модели, ошибка должна исчезнуть.
Я никогда не удаляю записи из таблицы, а помечаю флаг, который идентифицирует активна запись или нет. Я не хочу загружать неактивные записи в клиентское приложение. Каким образом всегда отфильтровывать их?
Вы должны добавить условие для колонки Active в вашем типе сущности. Затем нужно удалить сопоставление для колонки Active после чего совсем удалить ее из типа(именно в этом порядке). Рассмотрим следующий пример. Например у нас есть тип Entity2 у которое есть свойство Active. Это свойство типа bit в SQL Server.
Нам нужно добавить условие, которое указывает, что нужно получать данные только когда Active = 1, очистите сопоставление, затем удалите свойство из Entity2, как показано на следующем рисунке.
Теперь, вы будет получать записи у которых Active будет установлено в 1.
foreach (var e in context.Entity2)
Console.WriteLine(e.ID);
При этом, в клиентском приложении вам нужно будет добавить логику, которая будет устанавливать значение колонки Active в ноль, вместо удаления. Это можно сделать при помощи примерно такого кода:
public override int SaveChanges(SaveOptions options)
{
foreach (ObjectStateEntry entry in ObjectStateManager.GetObjectStateEntries(
EntityState.Deleted))
{
// Change the status to Unchanged, since we don't want for the Entity Framework
// to issue a delete command.
Entity2 e = entry.Entity as Entity2;
entry.ChangeState(EntityState.Unchanged);
// Update the Active columns in the database.
ExecuteStoreCommand("UPDATE Entity2 SET Active = 0 WHERE Entity2.ID = {0}", e.ID);
}
return base.SaveChanges(options);
}
Есть ли возможность сопоставлять представления на сложные типы?
Да. Entity Framework поддерживает сопоставление представлений в сложные типы. На самом деле представления не сильно отличаются от таблиц, но EF не имеет полной информации о них, в смысле ничего не знает о ключевых полях и тд. Обратите внимание, что сложные типы тоже не могут иметь ключей. Ключи могут быть созданы на основе одного или нескольких полей простых типов.
Каким образом указывать значения по умолчанию для столбцов? Для некоторых столбцов типа DateTime в моей базе данных установлено значение по умолчанию getdate(), но EF ничего не знает об этих значениях.
Если вы установите свойство StoreGeneratedPattern в значение Identity (если значение рассчитывается один раз, при добавлении записи в базу данных) или Computed (если значение рассчитывается при каждом обновлении записи), по при вызове метода SaveChanges EF получит рассчитываемое в БД значение и обновит объект. EF не будет автоматически обновлять значение при создании нового объекта, потому что значение рассчитывается в базе данных.
Следует заметить, что свойство StoreGeneratedPattern доступно в свойствах сущностей дизайнера EDM, только если вы использует подход “Модель сначала”. Если вы создаете модель из базы данных, то вам нужно будет самим обновить секцию SSDL файла EDMX добавив атрибут StoreGeneratedPattern в свойства сущности. Это будет исправлено в следующих выпусках дизайнера EF и свойство будет доступно и при разработке “Модель сначала” и “База данных сначала”.
Есть ли возможность сопоставлять хранимую процедуру к набору сопоставлений (association set) в дизайнере?
Нет.
[[articles:Entity Framework FAQ (ru-RU)|Содержание EF FAQ]]