ASP.NET Dynamic Data – что может быть проще?
Kartsev EvgenyОпубликовано 20.07.2009 в Разработка, Статьи
Содержание:
- Введение
- Системные требования
- База данных
- Основы ASP.NET Dynamic Data
- ASP.NET Dynamic Data deep dive
- Заключение
Введение
Новая библиотека Dynamic Data предназначена для быстрой генерации фронт-энда для баз данных SQL Server.
Ответ на вопрос – «Зачем мне это нужно?» будет рассмотрен в конце статьи.
Пример, рассматриваемый в статье, может показаться очень наивным и простым – я старался описать все мельчайшие подробности, чтобы охватить как можно бОльшую аудиторию читателей. Основная идея – меньше текста, больше картинок, поэтому разработчики с солидным опытом разработки на платформе .NET смогут понять весь процесс, просто просмотрев рисунки в статье.
Системные требования
- Windows XP SP2/Vista/Server 2003/Server 2008
- Visual Studio 2008 SP1 + .NET Framework 3.5 SP1
- SQL Server 2005/2008
Следует сделать одно важное замечание – необходимо, чтобы был установлен пакет обновлений SP1 для Visual Studio 2008, иначе при выборе вида проекта не появится необходимой опции – создание ASP.NET Dynamic Data Web Site.
База данных
В качестве базы данных для примера, рассматриваемого в статье, будет использована значительно упрощенная база данных, для хранения информации об авторах, книгах и издателях.

Рис 1. Схема тестовой базы данных
Существует список авторов (Authors) и издателей (Publishers). Также существует список книг (Books). Каждая книга может быть написана несколькими авторами, и принадлежать только одному издательству, у книги есть цена, которая не может быть менее 1 у.е. и более 1000 у.е., так же у книги есть дата публикации.
Итак, со схемой определились. Теперь приступим к созданию базы данных и наполнению ее тестовыми данными.
Открываем «SQL Server Management Studio» (Рис.2):

Рис 2. Запуск «SQL Server Management Studio»
Жмем кнопку «New Query» (Рис 3):

Рис 3. Создание нового запроса в SSMS
Копируем t-sql из листинга 1:
USE [master]
GO
IF EXISTS(SELECT 1 FROM sys.databases WHERE name='BookShop')
DROP DATABASE [BookShop]
CREATE DATABASE [BookShop]
GO
USE [BookShop]
GO
CREATE TABLE [Authors]
(
Id int IDENTITY(1,1) NOT NULL,
Name nvarchar(150) NULL
)
GO
CREATE TABLE [Books]
(
Id int IDENTITY(1,1) NOT NULL,
Name nvarchar(250) NOT NULL,
Description nvarchar(500) NULL,
IdPublisher int NOT NULL,
Price float NOT NULL,
PublishedAt datetime NOT NULL
)
GO
CREATE TABLE [BooksToAuthors]
(
IdBook int NOT NULL,
IdAuthor int NOT NULL
)
GO
CREATE TABLE [Publishers]
(
Id int IDENTITY(1,1) NOT NULL,
Name nvarchar(150) NOT NULL
)
GO
ALTER TABLE Authors ADD CONSTRAINT PK_Authors
PRIMARY KEY (Id)
GO
ALTER TABLE Books ADD CONSTRAINT PK_Books
PRIMARY KEY (Id)
GO
ALTER TABLE BooksToAuthors ADD CONSTRAINT PK_BooksToAuthors
PRIMARY KEY (IdBook,IdAuthor)
GO
ALTER TABLE Publishers ADD CONSTRAINT PK_Publishers
PRIMARY KEY (Id)
GO
ALTER TABLE Books ADD CONSTRAINT FK_Books_Publishers
FOREIGN KEY (IdPublisher) REFERENCES Publishers(Id)
GO
ALTER TABLE BooksToAuthors ADD CONSTRAINT FK_BooksToAuthors_Books
FOREIGN KEY (IdBook) REFERENCES Books(Id)
GO
ALTER TABLE BooksToAuthors ADD CONSTRAINT FK_BooksToAuthors_Author
FOREIGN KEY (IdAuthor) REFERENCES Authors(Id)
GO
Листинг 1. Скрипт для создания схемы базы данных
Жмем кнопку «Execute» (Рис. 4):
![]()
Рис 4. Запуск запроса
В результате в окне сообщения должны получить «Command(s) completed successfully».
Следующий шаг – заполнение только что созданной базы данных. Для этого выполняем запрос из листинга 2.
USE [BookShop]
GO
DELETE FROM BooksToAuthors
DELETE FROM Books
DELETE FROM Authors
DELETE FROM Publishers
INSERT INTO Authors (Name) VALUES ('Endrew Troelsen')
INSERT INTO Authors (Name) VALUES ('Matthew MacDonald')
INSERT INTO Authors (Name) VALUES ('Mario Szpuszta')
INSERT INTO Authors (Name) VALUES ('Eugene Kartsev')
INSERT INTO Publishers (Name) VALUES ('Apress')
INSERT INTO Publishers (Name) VALUES ('Williamspublishing')
INSERT INTO Publishers (Name) VALUES ('WROX')
INSERT INTO Books (Name, Description, IdPublisher, Price, PublishedAt)
VALUES ('Pro ASP.NET 3.5 in C#2008', '', (SELECT Id FROM Publishers WHERE Name='Apress'), '350.9900', GETDATE())
INSERT INTO Books (Name, Description, IdPublisher, Price, PublishedAt)
VALUES ('Another Interesting Book about .NET', '', (SELECT Id FROM Publishers WHERE Name='WROX'), '199.10', GETDATE())
INSERT INTO Books (Name, Description, IdPublisher, Price, PublishedAt)
VALUES ('Silverlight 2.0', '', (SELECT Id FROM Publishers WHERE Name='Williamspublishing'), '230.50', GETDATE())
INSERT INTO Books (Name, Description, IdPublisher, Price, PublishedAt)
VALUES ('Mu-mu, the beginning', '', (SELECT Id FROM Publishers WHERE Name='Apress'), '1.99', GETDATE())
INSERT INTO BooksToAuthors (IdBook, IdAuthor)
VALUES ((SELECT Id FROM Books WHERE Name='Pro ASP.NET 3.5 in C#2008'), (SELECT Id FROM Authors WHERE Name='Matthew MacDonald'))
INSERT INTO BooksToAuthors (IdBook, IdAuthor)
VALUES ((SELECT Id FROM Books WHERE Name='Pro ASP.NET 3.5 in C#2008'), (SELECT Id FROM Authors WHERE Name='Mario Szpuszta'))
INSERT INTO BooksToAuthors (IdBook, IdAuthor)
VALUES ((SELECT Id FROM Books WHERE Name='Another Interesting Book about .NET'), (SELECT Id FROM Authors WHERE Name='Endrew Troelsen'))
INSERT INTO BooksToAuthors (IdBook, IdAuthor)
VALUES ((SELECT Id FROM Books WHERE Name='Silverlight 2.0'), (SELECT Id FROM Authors WHERE Name='Matthew MacDonald'))
INSERT INTO BooksToAuthors (IdBook, IdAuthor)
VALUES ((SELECT Id FROM Books WHERE Name='Mu-mu, the beginning'), (SELECT Id FROM Authors WHERE Name='Eugene Kartsev'))
Листинг 2. Скрипт для наполнения БД тестовыми данными
Итак, тестовая база данных готова. Можно приступать к созданию сайта на основе ASP.NET Dynamic Data, но прежде следует сделать несколько замечаний.
Очень важно, чтобы структура базы данных была правильная (под правильностью понимается соответствие 3НФ). Данное требование особо остро ощущается при создании приложений на основании Dynamic Data или приложений, использующих автоматически сгенерированную схему классов LINQ2SQL. Но обо всем по порядку.
Основы ASP.NET Dynamic Data
Чтобы не тратить много времени на теорию, предлагаю начать с создания тестового приложения на базе Dynamic Data.
Запускаем Visual Studio 2008.
Выбираем File->New -> WebSite… (Рис 5):

Рис 5. Создание нового веб-сайта
Выбираем тип проекта «Dynamic Data Web Site» сохраняем его в папке «C:\TestApp\DynamicDataSite», если такой папки не существует, она будет создана (Рис 6):

Рис 6. Создание проекта «Dynamic Data Web Site»
После описанных выше шагов будет создан веб-сайт со структурой как показано на рисунке 7:

Рис 7. Структура проекта «ASP.NET Dynamic Data Web Site»
Следующий шаг – генерация классов LINQ2SQL на основании созданной базы данных.
Добавляем «LINQ to SQL Classes» с именем «BookShop.dbml» (рис 8-9):

Рис 8. Добавление LINQ2SQL классов, шаг 1

Рис 9. Добавление LINQ2SQL классов, шаг 2
Visual Studio предложит сохранить сгенерированные классы в папке «App_Code» (Рис 10). Согласимся с этим – жмем «Yes»:

Рис 10. Сохранение файлов с C# кодом в папке «App_Code»
Далее будет открыт дизайнер LINQ2SQL, в который необходимо перенести таблицы из базы данных.
Открываем «Server Explorer» в Visual Studio и добавляем новый коннекшн к тестовой базе данных (Рис 11):

Рис 11. Добавление нового соединения к БД
Вписываем необходимые параметры в окне «Add Connection» и жмем кнопку «Test Connection» (Рис 12):

Рис 12. Форма «Add Connection»
Результат тестирования коннекшна должно быть окно, показанное на рис. 13:

Рис 13. Удачное тестирование соединения с БД
Если вы получили ошибку соединения – необходимо вернуться на шаг назад и проверить правильность ввода данных в окне «Add Connection».
После выполненных шагов переносим таблицы из базы данных «BookShop» на форму дизайнера LINQ2SQL (Рис 14):

Рис 14. Перенос таблицы из «Server Explorer» на форму дизайнера «LINQ2SQL»
В результате генерирования сущностей LINQ2SQL дизайнер должен выглядить приблизительно так-же как и на рис. 15:

Рис 15. Сущности на дизайнере LINQ2SQL
Следующим шагом необходимо раскомментировать строку в файле «Global.asax»:
model.RegisterContext(typeof(BookShopDataContext), new ContextConfiguration() { ScaffoldAllTables = true });
Хочу обратить ваше внимание, что необходимо подменить значение «YourDataContextType» на «BookShopDataContext», а также поменять значение параметра «ScaffoldAllTables» с false на true.
Параметр «ScaffoldAllTables» указывает на то, что необходимо взять все таблицы из модели LINQ2SQL и сгенерировать для них формы.
Вот и все, что нужно сделать для того, чтобы сайт работал – следующим шагом жмем кнопку «Save All», после чего жмем «F5» и тестируем работоспособность сайта (Рис 16-17):

Рис 16. Тестирование сгенерированного веб-сайта
Рис 17. Тестирование сгенерированного веб-сайта
Сгенерированный веб-сайт – полностью работоспособное приложение, которое является «Лицом» базы данных и позволяет делать CRUD (Create, Read, Update, Delete) операции со всеми сущностями БД + простую выборку.
Вывод: Используя ASP.NET Dynamic Data можно, потратив 15 минут, создать полностью работоспособное приложение, не написав при этом ни строчки кода.
ASP.NET Dynamic Data deep dive
Модель программирования в Dynamic Data основана на атрибутах, поэтому прежде чем приступать к рассмотрению примера «кастомизации» веб-приложения, предлагаю ознакомиться со списком основных атрибутов в мире Dynamic Data. Исчерпывающая информация об атрибутах можно найти в блоге Maira Wenzel.
Описание атрибутов для классов (Сущностей):
| Attribute name | Description |
|---|---|
TableName |
Имя таблицы, которое будет использоваться в url, в списке таблиц на главной странице, а также в качестве имени в разделе. |
DisplayColumn |
Первый параметр атрибута – имя колонки, которое будет использоваться по умолчанию в DropDownList в других разделах на сайте (где есть Foreign Key на текущее свойство). Второй параметр – имя колонки, по которой должна осуществляться сортировка. |
ScaffoldTable |
True|False – отображает или скрывает таблицу. По умолчанию равен True. |
Описание атрибутов для свойств (Property):
| Attribute name | Description |
|---|---|
Required |
Определяет является ли свойство обязательным. Необходимо для валидации. Если равно True, при создании новой записи поле не может быть пустым. |
StringLength |
Определяет длину строки, которое может быть введено в текстовое поле, сгенерированное для свойства. Нужен для валидации. |
Description |
Определяет текст, который будет появляться при наведении курсора на элемент управления (tooltip) в режиме редактирования. |
DisplayName |
Имя свойства, которое будет отображаться в качестве названия колонки (header) в List Mode, а также в качестве названия редактируемого поля в Edit Mode. |
DefaultValue |
Значение по умолчанию, которое будет использовано во-время создания новой записи. |
RegularExpression |
Определяет регулярное выражение, которое будет использовано для валидации значения введенного в элемент управления в режиме редактирования. |
DataType |
Тип данных в который будет конвертироваться значение введенное в элемент управления. |
DisplayFormat |
Формат, для отображения значения свойства в Display|List|Edit режимах. |
Range |
Определяет минимальное и максимальное значение, которое может быть введено в элемент управления. |
ScaffoldColumn |
Определяет, необходимо ли показывать/скрывать свойство. |
UIHint |
Определяем «кастомный» элемент управления для отображения данных свойства. |
На рис.18 представлена схема взаимодействия сущностей с типами Metadata. В общей схеме есть сущности, которые были сгенерированы из базы данных (LINQ2SQL Entities). Так как сгенерированные сущности помечены как partial – это означает, то можно (и нужно) реализовать вторую часть класса.
В конечном итоге, необходимо сделать 2 шага:
1 – Реализовать класс Metadata, который будет содержать описание для необходимых свойств. Сигнатура свойств в классе Metadata должна быть идентичной сигнатуре свойств в классе, сгенерированном LINQ2SQL.
2 – Реазиловать вторую часть сгенерированного LINQ2SQL класса, помеченного как partial и добавить к нему атрибут MetadataType.
Итак, продолжим рассмотрение примера…
Создаем 2 дополнительные папки с именами «BusinessObjects» и «Metadata» в папке «App_Code», в которых создаем файлы бизнес объектов и Metadata, как показано на рис. 19:

Рис 19. Файлы бизнес объектов и мета-информации.
Для простоты примера опишем только сущность «Book», остальные пометим атрибутом [ScaffoldTable(false)] для того, чтобы не показывать эти таблицы на сайте.
Author.cs:
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(AuthorMetadata))]
public partial class Author
{
}
AuthorMetadata.cs:
using System.ComponentModel.DataAnnotations;
[ScaffoldTable(false)]
public class AuthorMetadata
{
}
BooksToAuthor.cs:
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(BooksToAuthorMetadata))]
public partial class BooksToAuthor
{
}
BooksToAuthorMetadata.cs:
using System.ComponentModel.DataAnnotations;
[ScaffoldTable(false)]
public class BooksToAuthorMetadata
{
}
Publisher.cs:
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(PublisherMetadata))]
public partial class Publisher
{
}
PublisherMetadata.cs:
using System.ComponentModel.DataAnnotations;
[ScaffoldTable(false)]
public class PublisherMetadata
{
}
Итак, рассмотрим основные классы:
Book.cs:
using System.ComponentModel.DataAnnotations;
[MetadataType(typeof(BookMetadata))]
public partial class Book
{
}
BookMetadata.cs:
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data.Linq;
using System.Web.DynamicData;
[TableName("Книги")]
[DisplayColumn("Name", "Name")]
public class BookMetadata
{
[Required(ErrorMessage = "Поле 'Имя книги' не может быть пустым")]
[StringLength(250)]
[Description("Официальное имя книги")]
[DisplayName("Имя книги")]
[DefaultValue("<Введите имя книги>")]
[RegularExpression("(?!^<Введите имя книги>$).*", ErrorMessage = "Необходимо внести корректное название книги")]
public string Name { get; set; }
[Description("Краткое описание книги")]
[DisplayName("Описание книги")]
[DataType(DataType.MultilineText)]
public string Description { get; set; }
[Description("Цена книги")]
[DisplayName("Цена")]
[DisplayFormat(DataFormatString = "{0:F2}", ApplyFormatInEditMode = true)]
[Required(ErrorMessage = "Поле 'Цена' не может быть пустым")]
[Range(1, 1000, ErrorMessage = "Значение должно быть в пределах 1-1000")]
public double Price { get; set; }
[Description("Издательский дом")]
[DisplayName("Издатель")]
public Publisher Publisher { get; set; }
[ScaffoldColumn(false)]
public EntitySet<BooksToAuthor> BooksToAuthors { get; set; }
}
Назначение атрибутов рассматривается на рисунке 20:

Рис 21. Маппинг атрибутов
В существующей модели есть одно очень важное ограничение – поле для даты (PublishedAt) это текстовое поле, хоть оно и валидируется, но все же неудобно использовать текстовое поле для ввода даты.
Чтобы решить эту проблему необходимо реализовать «TemplateField» элемент управления и добавить его в модель.
Сделаем это…
Добавляем 2 *.ascx элемента управления в папку «FieldTemplates» с именами «RichDateTime.ascx» и «RichDateTime_Edit.ascx» соответственно. Первый для отображения данных в List Mode, второй для отображения данных в Edit Mode (Рис 21):

Рис 21. Файлы для реализации «TemplateField»
Код в файлах:
RichDateTime.ascx:
<%@ Control Language="C#" AutoEventWireup="true"
CodeFile="RichDateTime.ascx.cs"
Inherits="DynamicData_FieldTemplates_RichDateTime" %>
<asp:Literal ID="dateTime" runat="server" Text="<%# FieldValueString %>" />
RichDateTime.ascx.cs:
using System.Web.DynamicData;
using System.Web.UI;
public partial class DynamicData_FieldTemplates_RichDateTime : FieldTemplateUserControl
{
public override Control DataControl
{
get { return dateTime; }
}
}
RichDateTime_Edit.ascx:
<%@ Control Language="C#" AutoEventWireup="true"
CodeFile="RichDateTime_Edit.ascx.cs"
Inherits="DynamicData_FieldTemplates_RichDateTime_Edit" %>
<asp:Calendar ID="calendar" runat="server" />
RichDateTime_Edit.ascx.cs:
using System.Web.DynamicData;
using System.Web.UI;
public partial class DynamicData_FieldTemplates_RichDateTime_Edit : FieldTemplateUserControl
{
protected override void ExtractValues(System.Collections.Specialized.IOrderedDictionary dictionary)
{
dictionary[Column.Name] = ConvertEditedValue(calendar.SelectedDate.ToString());
}
public override Control DataControl
{
get
{
return calendar;
}
}
}
Далее добавляем новое свойство в класс «BookMetadata.cs» с нужными атрибутами:
[DisplayFormat(DataFormatString = "{0:mm-dd-yyyy}")]
[UIHint("RichDateTime")]
public DateTime PublishedAt { get; set; }
Сохраняем и запускаем сайт. Результат показан на рис. 22:

Рис 22. Результат применения TemplateField к свойству с типом DateTime
Как видим, добавление нового View в модель – невероятно простая задача.
Заключение
Итак, ответим на вопрос в начале статьи: «Зачем мне это нужно?» – ASP.NET Dynamic Data – гибкий фреймворк для очень быстрого построения FrontEnd для базы данных SQL Server. Для всех, кто хочет сохранить свое время – категорически рекомендую ознакомиться с этой технологией поближе, это позволит вам сэкономить несколько дней, а то и недель на разработку.
В ASP.NET Dynamic Data существует еще одно очень мощное и гибкое средство, которое называется «Dynamic Data Filtering». На момент написания статьи данное средство поставляется в виде отдельной сборки, которую можно бесплатно загрузить с сайта codeplex.com.
Как и все средства, Dynamic Data имеет ряд ограничений:
- в качестве БД может быть только SQL Server 2005/2008
- существует проблема при переходе из List в Edit Mode – т.к. на странице List.aspx используется UpdatePanel для AJAX запросов, в случае если существует достаточно большое количесвто данных – скажем, более 20 появится, пэйджер (Pager) для перехода к другим страницам в GridView. Проблема в том, что когда мы переходим в Edit Mode со страници List.aspx, и жмем на странице Edit.aspx линк «Update» или «Cancel» возвращаемся на страницу List.aspx, при этом Pager будет установлен на 1-ю страницу, а не на ту, которая была выбрана до перехода на Edit.aspx. Самый простой способ решения проблемы использование ListDetails.aspx вместо List.aspx -> Edit.aspx, при этом все действия будут осуществляться на одной странице и не будет потеряно значение в поле Pager.
Что почитать?
- рекомендую посетить сайт www.asp.net и посмотреть скринкасты «ASP.NET Dynamic Data»
- блог Maira Wenzel
- блог Josh Heyse
- Dynamic Data Filtering
- книга «Secrets of Real World ASP.NET Dynamic Data Web Sites», автор Craig Shoemaker. К сожалению, на момент написания статьи данная книга еще не была выпущена, но есть надежда что она появится весьма скоро.
Понравилась статья? Подпишись на обновления по RSS/E-mail



(32 голосов, средний: 4.34 из 5)
Интересная технология. Кто юзал, поделитесь впечатлениями?
С использованием ASP.NET Dynamic Data я разрабатывал наш корпоративный сайт http://www.innovinn.com/. Сайт динамический (мини CMS), весь контент лежит в базе. ASP.NET Dynamic Data использует routing из ASP.NET MVC.
Процедура следующая:
создается база данных
админка под нее – ASP.NET Dynamic Data
пишется “морда” по собственному усмотрению.
В общем, очень быстро и удобно. Есть свои проблемы (например, такая), но это все можно настроить и расширить.
P.S. Посмотрел на оценки статьи. Мне интересно мнение тех, кто поставил 2 или 3 бала – чем это вызвано? Плохая статья, не нравиться технология, день плохой? Вы бы аргументировали, за что ставите низкие оценки. Ведь статья действительно хорошая и полезная. Что вы оцениваете?
P.S.S. Никакого отношения к автору не имею, просто ИМХО.
Область применения крайне узкая. Среднестатический клиент обязательно захочет кучу дополнительных фич.
Куча дополнительных фич добавляется очень быстро и не сложно. В целом, время на разработку сокращается в разы.
Дежавю прям какое то
MS back to MS Access – нуу будет работать для каких то тривиальных задач, а шаг влево/вправо так сразу появляется гора кода и все эти ускорители начинают только мешать.
2 shadow:
Все дело в том, что в других фрэймворках гора кода появится с самого начала. Несомненно нужно будет что-то писать ручками, иначе была бы утопия.
Думаю проблема в голосовалке – имхо неудобная. Сам по-неосторожности поставил себе 3 балла
Соглашусь с Жека по поводу кучи кода. Думаю здесь нужно соблюдать границы между тем что можно на автомате решить и тем что достаточно сложно и требует более глубокого вмешательства со стороны разработчика.
по поводу
– если не ошибаюсь это стандартная фича в 3.5.
2 Denis Osetrov:
Вы все же ошибаетесь. Никто не запрещает писать приложения на .NET 3.5 , используя стандартные ASP.NET WebForms без роутинга. То что это фича .NET 3.5 – это бесспорно.
Имелось ввиду, что роутинг пришел в WebForms из MVC.
“категорически рекомендую” — это что-то из недавнего Дилберта
Всё хорошо, кроме гемора с атрибутами: эту кучу надо помнить все наизусть и
вводить вручную? А нет ли какой соответствующей Property Page?
Любая технология многоуровневой MDD (например, такая) в реальных условиях “делает на раз” это чудо майкрософтовской инженерной мысли по всем статьям.
ДинДата шлак – ф топку ))
2 Виталий: вы судите из личного опыта работы с ДД? мне просто интерсно мнение тех, кто реально юзал это чудо от МС.
2 Виталий: кста, спс за ссылку на NReco. весьма интересно.
Попробовал. Но вместо LINQ to SQL использовал LINQ to Entities. Запустилось нормально. Но при клике по имени таблицы, сразу же получаем ошибку:
“The method ‘Skip’ is only supported for sorted input in LINQ to Entities. The method ‘OrderBy’ must be called before the method ‘Skip’”.
Ошибка где-то в недрах. В исходники не вываливаемся. Что это может быть? Вроде в комментах в Global.asax.cs написано что можно LINQ to Entities юзать:
“Uncomment this line to register LINQ to SQL classes or an ADO.NET Entity Data model for ASP.NET Dynamic Data.”
INSERT INTO Books (Name, Description, IdPublisher, Price, PublishedAt)
VALUES (’Pro ASP.NET 3.5 in C#2008′, ”, (SELECT Id FROM Publishers WHERE Name=’Apress’), ‘350.9900′, GETDATE())
2005 не позволяет:
Msg 1046, Level 15, State 1, Line 17
Subqueries are not allowed in this context. Only scalar expressions are allowed.
Увы, коллеги,
Что-то не получается создать сайт в соответствии с рекомендациями автора
Все сделал по его довольно простой схеме, сайт сгенерировался, но при ссылке на любую таблицу получаю ошибку:
…System.InvalidCastException: Не удалось привести тип объекта “TypesObjectsDataContext” к типу “System.Data.Objects.ObjectContext”…
Может подсажите в чем дело, Можно на e-mail alevv@bigmir.net
Celamoi, какую модель вы генерировали? Linq2Sql или EF? Попробуйте описать подробнее…
Спасибо, что быстро откликнулись, Жека !
Я генерировал модель Linq2Sql, как и было описано в статье. По нажатию F5 как положено запустиля тестовый IIS, запустился Internet Explorer
со сгенерированым сайтом (все как описано в статье), но переход по любой ссылке, обозначающей таблицу вызывал следующую ошибку (цитирую полностью – может модератор пропустит) :
Не удалось привести тип объекта "TypesObjectsDataContext" к типу "System.Data.Objects.ObjectContext".
Описание: Необработанное исключение при выполнении текущего веб-запроса. Изучите трассировку стека для получения дополнительных сведений о данной ошибке и о вызвавшем ее фрагменте кода.
Сведения об исключении: System.InvalidCastException: Не удалось привести тип объекта "TypesObjectsDataContext" к типу "System.Data.Objects.ObjectContext".
Ошибка источника:
Необработанное исключение при выполнении текущего веб-запроса. Информацию о происхождении и месте возникновения исключения можно получить, используя следующую трассировку стека исключений.
Трассировка стека:
[InvalidCastException: Не удалось привести тип объекта "TypesObjectsDataContext" к типу "System.Data.Objects.ObjectContext".]
System.Web.UI.WebControls.EntityDataSourceView.ConstructContext() +391
System.Web.UI.WebControls.EntityDataSourceView.ExecuteSelect(DataSourceSelectArguments arguments, Creator qbConstructor) +97
System.Web.UI.WebControls.EntityDataSourceView.ExecuteSelect(DataSourceSelectArguments arguments) +154
System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback) +19
System.Web.UI.WebControls.DataBoundControl.PerformSelect() +142
System.Web.UI.WebControls.BaseDataBoundControl.DataBind() +73
System.Web.UI.WebControls.GridView.DataBind() +4
System.Web.UI.WebControls.BaseDataBoundControl.EnsureDataBound() +82
System.Web.UI.WebControls.CompositeDataBoundControl.CreateChildControls() +72
System.Web.UI.Control.EnsureChildControls() +87
System.Web.UI.Control.PreRenderRecursiveInternal() +44
System.Web.UI.Control.PreRenderRecursiveInternal() +171
System.Web.UI.Control.PreRenderRecursiveInternal() +171
System.Web.UI.Control.PreRenderRecursiveInternal() +171
System.Web.UI.Control.PreRenderRecursiveInternal() +171
System.Web.UI.Control.PreRenderRecursiveInternal() +171
System.Web.UI.Control.PreRenderRecursiveInternal() +171
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +842
________________________________________
Информация о версии: Платформа Microsoft .NET Framework, версия:2.0.50727.3603; ASP.NET, версия:2.0.50727.3082
может дело в последней строке, которая возможно показывает что не подключился Framework 3.5,
но у меня эта версия установлена и, вроде по умолчанию VS 2008 должен использовать именно ее ?
Я немного скорректировал запрос по наполнению БД. А то вложенные запросы не работали:
USE [BookShop]
GO
DELETE FROM BooksToAuthors
DELETE FROM Books
DELETE FROM Authors
DELETE FROM Publishers
INSERT INTO Authors (Name) VALUES (’Endrew Troelsen’);
INSERT INTO Authors (Name) VALUES (’Matthew MacDonald’);
INSERT INTO Authors (Name) VALUES (’Mario Szpuszta’);
INSERT INTO Authors (Name) VALUES (’Eugene Kartsev’);
INSERT INTO Publishers (Name) VALUES (’Apress’);
INSERT INTO Publishers (Name) VALUES (’Williamspublishing’);
INSERT INTO Publishers (Name) VALUES (’WROX’);
INSERT INTO Books (Name, Description, IdPublisher, Price, PublishedAt)
SELECT ‘Pro ASP.NET 3.5 in C#2008′, ”, Id, ‘350.9900′, GETDATE() FROM Publishers WHERE Name=’Apress’;
INSERT INTO Books (Name, Description, IdPublisher, Price, PublishedAt)
SELECT ‘Another Interesting Book about .NET’, ”, ID, ‘199.10′, GETDATE() FROM Publishers WHERE Name=’WROX’;
INSERT INTO Books (Name, Description, IdPublisher, Price, PublishedAt)
SELECT ‘Silverlight 2.0′, ”, Id, ‘230.50′, GETDATE() FROM Publishers WHERE Name=’Williamspublishing’;
INSERT INTO Books (Name, Description, IdPublisher, Price, PublishedAt)
SELECT ‘Mu-mu, the beginning’, ”, ID, ‘1.99′, GETDATE() FROM Publishers WHERE Name=’Apress’;
INSERT INTO BooksToAuthors (IdBook, IdAuthor)
SELECT * From
(SELECT Id FROM Books WHERE Name=’Pro ASP.NET 3.5 in C#2008′) a1,
(SELECT Id FROM Authors WHERE Name=’Matthew MacDonald’) a2;
INSERT INTO BooksToAuthors (IdBook, IdAuthor)
SELECT * FROM
(SELECT Id FROM Books WHERE Name=’Pro ASP.NET 3.5 in C#2008′) a1,
(SELECT Id FROM Authors WHERE Name=’Mario Szpuszta’) a2;
INSERT INTO BooksToAuthors (IdBook, IdAuthor)
SELECT * FROM
(SELECT Id FROM Books WHERE Name=’Another Interesting Book about .NET’) a1,
(SELECT Id FROM Authors WHERE Name=’Endrew Troelsen’) a2;
INSERT INTO BooksToAuthors (IdBook, IdAuthor)
SELECT * FROM
(SELECT Id FROM Books WHERE Name=’Silverlight 2.0′) a1,
(SELECT Id FROM Authors WHERE Name=’Matthew MacDonald’) a2;
INSERT INTO BooksToAuthors (IdBook, IdAuthor)
SELECT * FROM
(SELECT Id FROM Books WHERE Name=’Mu-mu, the beginning’) a1,
(SELECT Id FROM Authors WHERE Name=’Eugene Kartsev’) a2;
А почему не все столбцы отображаются в List.aspx? Хочу чтобы были видны все, а показывает както выборочн (((
сочуствую автору,
ведь он читает весь этот бред тупых и убогих,
которым
1) впадлу сходить по рефренсам, указанным в “Что почитать?”
2) погуглить
3,4 и т.д ) включить мозг, вынуть из жопы руки, приделать их на место и заняться делом
технологии больше года, а
людине могут понять и разобраться..ЖЕНЯ! ДЕРЖИСЬ!
В процессе обсуждения решаются спорные вопросы, порой не ведомые даже автору, поэтому не думаю что люди, которые тут пишут относятся к категории “Тупые и убогие”.
Соглашусь лишь с тем, что список источников в конце статьи все же нужно хотя бы просматривать
Всем спасибо за комментарии!
дико извиняюсь
есть-жешь МСДН, asp.net/dynamicdata, techdays.ru наконец-концов…
за то что причислил всех, это конечно(!) же не так 8D..
но люди! че-ло-ве-ки!
так ж незя
и вообще,все будет харашо! все будет
еще раз сорри за резкость и сорри за алпанский – это мой, близкий по духу, ясцзык..
ЗЫ я против расовой или какой либо другой ненависти – поэтому разрешаю килльнуть все мои посты, дабы не раздрАживать окружающую действительность
ЗЗЫ сорри за оффтоп и непотемак
ЗЗЗЫ какова вероятность что капча два раза за два дня спросит про 3+6 ?