×Закрыть

ASP. NET Dynamic Data — что может быть проще?

Содержание:

  1. Введение
  2. Системные требования
  3. База данных
  4. Основы ASP. NET Dynamic Data
  5. ASP. NET Dynamic Data deep dive
  6. Заключение

Введение

Новая библиотека 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.

База данных

В качестве базы данных для примера, рассматриваемого в статье, будет использована значительно упрощенная база данных, для хранения информации об авторах, книгах и издателях.

db structure

Рис 1. Схема тестовой базы данных

Существует список авторов (Authors) и издателей (Publishers). Также существует список книг (Books). Каждая книга может быть написана несколькими авторами, и принадлежать только одному издательству, у книги есть цена, которая не может быть менее 1 у. е. и более 1000 у. е., так же у книги есть дата публикации.

Итак, со схемой определились. Теперь приступим к созданию базы данных и наполнению ее тестовыми данными.

Открываем «SQL Server Management Studio» (Рис.2):

Open SSMS

Рис 2. Запуск «SQL Server Management Studio»

Жмем кнопку «New Query» (Рис 3):

new query

Рис 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):

Execute button

Рис 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):

new web site

Рис 5. Создание нового веб-сайта

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

_6 Dynamic Data Web Site

Рис 6. Создание проекта «Dynamic Data Web Site»

После описанных выше шагов будет создан веб-сайт со структурой как показано на рисунке 7:

Dynamic created web site

Рис 7. Структура проекта «ASP. NET Dynamic Data Web Site»

Следующий шаг — генерация классов LINQ2SQL на основании созданной базы данных.

Добавляем «LINQ to SQL Classes» с именем «BookShop.dbml» (рис 8−9):

8 Add new item

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

Add linq 2 sql

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

Visual Studio предложит сохранить сгенерированные классы в папке «App_Code» (Рис 10). Согласимся с этим — жмем «Yes»:

Save to App_Code folder

Рис 10. Сохранение файлов с C# кодом в папке «App_Code»

Далее будет открыт дизайнер LINQ2SQL, в который необходимо перенести таблицы из базы данных.

Открываем «Server Explorer» в Visual Studio и добавляем новый коннекшн к тестовой базе данных (Рис 11):

Server Explorer

Рис 11. Добавление нового соединения к БД

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

Add connection

Рис 12. Форма «Add Connection»

Результат тестирования коннекшна должно быть окно, показанное на рис. 13:

Connection Succeeded

Рис 13. Удачное тестирование соединения с БД

Если вы получили ошибку соединения — необходимо вернуться на шаг назад и проверить правильность ввода данных в окне «Add Connection».

После выполненных шагов переносим таблицы из базы данных «BookShop» на форму дизайнера LINQ2SQL (Рис 14):

BookShop tables

Рис 14. Перенос таблицы из «Server Explorer» на форму дизайнера «LINQ2SQL»

В результате генерирования сущностей LINQ2SQL дизайнер должен выглядить приблизительно так-же как и на рис. 15:

LINQ2SQL Entities

Рис 15. Сущности на дизайнере LINQ2SQL

Следующим шагом необходимо раскомментировать строку в файле «Global.asax»:

model.RegisterContext(typeof(BookShopDataContext), new ContextConfiguration() { ScaffoldAllTables = true });

Хочу обратить ваше внимание, что необходимо подменить значение «YourDataContextType» на «BookShopDataContext», а также поменять значение параметра «ScaffoldAllTables» с false на true.

Параметр «ScaffoldAllTables» указывает на то, что необходимо взять все таблицы из модели LINQ2SQL и сгенерировать для них формы.

Вот и все, что нужно сделать для того, чтобы сайт работал — следующим шагом жмем кнопку «Save All», после чего жмем «F5» и тестируем работоспособность сайта (Рис 16−17):

Dynamic data default page

Рис 16. Тестирование сгенерированного веб-сайта

BooksToAuthors page

Рис 17. Тестирование сгенерированного веб-сайта

Сгенерированный веб-сайт — полностью работоспособное приложение, которое является «Лицом» базы данных и позволяет делать CRUD (Create, Read, Update, Delete) операции со всеми сущностями БД + простую выборку.

Вывод: Используя ASP. NET Dynamic Data можно, потратив 15 минут, создать полностью работоспособное приложение, не написав при этом ни строчки кода.

ASP. NET Dynamic Data deep dive

Модель программирования в Dynamic Data основана на атрибутах, поэтому прежде чем приступать к рассмотрению примера «кастомизации» веб-приложения, предлагаю ознакомиться со списком основных атрибутов в мире Dynamic Data. Исчерпывающая информация об атрибутах можно найти в блоге Maira Wenzel.

Описание атрибутов для классов (Сущностей):

Attribute nameDescription
TableNameИмя таблицы, которое будет использоваться в url, в списке таблиц на главной странице, а также в качестве имени в разделе.
DisplayColumnПервый параметр атрибута — имя колонки, которое будет использоваться по умолчанию в DropDownList в других разделах на сайте (где есть Foreign Key на текущее свойство). Второй параметр — имя колонки, по которой должна осуществляться сортировка.
ScaffoldTableTrue|False — отображает или скрывает таблицу. По умолчанию равен True.

Описание атрибутов для свойств (Property):

Attribute nameDescription
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.

Metadata Scheme

Итак, продолжим рассмотрение примера...

Создаем 2 дополнительные папки с именами «BusinessObjects» и «Metadata» в папке «App_Code», в которых создаем файлы бизнес объектов и Metadata, как показано на рис. 19:

Add classes to project

Рис 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:
Attributes Mapping

Рис 21. Маппинг атрибутов

В существующей модели есть одно очень важное ограничение — поле для даты (PublishedAt) это текстовое поле, хоть оно и валидируется, но все же неудобно использовать текстовое поле для ввода даты.

Чтобы решить эту проблему необходимо реализовать «TemplateField» элемент управления и добавить его в модель.

Сделаем это...

Добавляем 2 *.ascx элемента управления в папку «FieldTemplates» с именами «RichDateTime.ascx» и «RichDateTime_Edit.ascx» соответственно. Первый для отображения данных в List Mode, второй для отображения данных в Edit Mode (Рис 21):

Add ascx

Рис 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[<a href="http://Column.Name" target="_blank">Column.Name</a>] = 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:

TemplateField Result

Рис 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. К сожалению, на момент написания статьи данная книга еще не была выпущена, но есть надежда что она появится весьма скоро.
  • Популярное

28 комментариев

Подписаться на комментарииОтписаться от комментариев Комментарии могут оставлять только пользователи с подтвержденными аккаунтами.

Коллеги! Хочу предложить вашему вниманию свой проект, который основывается на ASP.NET Dynamic Data и является развитием этой технологии!
Ознакомиться с проектом можно тут: github.com/...x/X.DynamicData

Не получается сделать binding к dropdownlist из-за чего это может быть? биндинг проверил в обычном проекте работает.выкрутился так:

SqlDataReader sdr = cmd.ExecuteReader(); while (sdr.Read()) { dropDown.Items.Add(sdr["name"].ToString()); }

но все равно нужно биндинг как то делать

Всё гуд, за час работы написал, хорошую админку, а ещё в статье увидел ссылку на ASP.NET Dynamic Data Filtering и вообще паражен как все просто, останется только добавить дизайн и всё.

дико извиняюсьза то что причислил всех, это конечно (!) же не так 8D...но люди! че-ло-ве-ки! так ж незя:) есть-жешь МСДН, asp.net/dynamicdata, techdays.ru наконец-концов...и вообще, все будет харашо! все будет:) еще раз сорри за резкость и сорри за алпанский — это мой, близкий по духу, ясцзык...ЗЫ я против расовой или какой либо другой ненависти — поэтому разрешаю килльнуть все мои посты, дабы не раздрАживать окружающую действительность:) ЗЗЫ сорри за оффтоп и непотемакЗЗЗЫ какова вероятность что капча два раза за два дня спросит про 3+6?:)

В процессе обсуждения решаются спорные вопросы, порой не ведомые даже автору, поэтому не думаю что люди, которые тут пишут относятся к категории «Тупые и убогие».Соглашусь лишь с тем, что список источников в конце статьи все же нужно хотя бы просматривать:) Всем спасибо за комментарии!

сочуствую автору, ведь он читает весь этот бред тупых и убогих, которым 1) впадлу сходить по рефренсам, указанным в "Что почитать? "2) погуглить3, 4 и т.д) включить мозг, вынуть из жопы руки, приделать их на место и заняться деломтехнологии больше года, а люди не могут понять и разобраться...ЖЕНЯ! ДЕРЖИСЬ!

А почему не все столбцы отображаются в List.aspx? Хочу чтобы были видны все, а показывает както выборочн (((

Я немного скорректировал запрос по наполнению БД. А то вложенные запросы не работали: USE [BookShop] GODELETE FROM BooksToAuthorsDELETE FROM BooksDELETE FROM AuthorsDELETE FROM PublishersINSERT 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;

Спасибо, что быстро откликнулись, Жека! Я генерировал модель 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 должен использовать именно ее?

Celamoi, какую модель вы генерировали? Linq2Sql или EF? Попробуйте описать подробнее...

Увы, коллеги, Что-то не получается создать сайт в соответствии с рекомендациями автора Все сделал по его довольно простой схеме, сайт сгенерировался, но при ссылке на любую таблицу получаю ошибку: ...System.InvalidCastException: Не удалось привести тип объекта «TypesObjectsDataContext» к типу «System.Data.Objects.ObjectContext»...Может подсажите в чем дело, Можно на e-mail alevv@bigmir.net

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 17Subqueries are not allowed in this context. Only scalar expressions are allowed.

Попробовал. Но вместо 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.”

2 Виталий: кста, спс за ссылку на NReco. весьма интересно.

2 Виталий: вы судите из личного опыта работы с ДД? мне просто интерсно мнение тех, кто реально юзал это чудо от МС.

Любая технология многоуровневой MDD (например, такая) в реальных условиях «делает на раз» это чудо майкрософтовской инженерной мысли по всем статьям.ДинДата шлак — ф топку))

Всё хорошо, кроме гемора с атрибутами: эту кучу надо помнить все наизусть и вводить вручную? А нет ли какой соответствующей Property Page?


категорически рекомендую’’ — это что-то из недавнего Дилберта:)

ASP.NET Dynamic Data использует routing из ASP.NET MVC. — если не ошибаюсь это стандартная фича в 3.5.

Имелось ввиду, что роутинг пришел в WebForms из MVC.

2 Denis Osetrov: Вы все же ошибаетесь. Никто не запрещает писать приложения на.NET 3.5, используя стандартные ASP.NET WebForms без роутинга. То что это фича.NET 3.5 — это бесспорно.

Соглашусь с Жека по поводу кучи кода. Думаю здесь нужно соблюдать границы между тем что можно на автомате решить и тем что достаточно сложно и требует более глубокого вмешательства со стороны разработчика.по поводу

ASP.NET Dynamic Data использует routing из ASP.NET MVC.

— если не ошибаюсь это стандартная фича в 3.5.

P.S. Посмотрел на оценки статьи...

Думаю проблема в голосовалке — имхо неудобная. Сам по-неосторожности поставил себе 3 балла:)

2 shadow: Все дело в том, что в других фрэймворках гора кода появится с самого начала. Несомненно нужно будет что-то писать ручками, иначе была бы утопия.

Дежавю прям какое то; -) MS back to MS Access — нуу будет работать для каких то тривиальных задач, а шаг влево/вправо так сразу появляется гора кода и все эти ускорители начинают только мешать.

клиент обязательно захочет кучу дополнительных фич.

Куча дополнительных фич добавляется очень быстро и не сложно. В целом, время на разработку сокращается в разы.

Область применения крайне узкая. Среднестатический клиент обязательно захочет кучу дополнительных фич.

С использованием 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. Никакого отношения к автору не имею, просто ИМХО.

Интересная технология. Кто юзал, поделитесь впечатлениями?

Подписаться на комментарии