Форум программистов, компьютерный форум, киберфорум
Наши страницы
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 26, средняя оценка - 4.88
Void-87
2 / 2 / 1
Регистрация: 22.06.2012
Сообщений: 244
#1

Организация Data Access Layer - C#

08.12.2013, 08:54. Просмотров 4436. Ответов 18
Метки нет (Все метки)

Здравствуйте.

В книгах как-то слишком абстрактно все описано, хочется хоть какой-то конкретики.

Понятно лишь, то, что клиент (слой представления)должен обращаться к ДАЛ, через интерфейс, дабы можно было менять слои в случае чего как хотим.

Вопрос в том, каким должен быть примерно этот интерфейс и к чему конкретно в ДАЛ он должен быть прикручен.

Я вижу это примерно так. В ДАЛ следует определить некий класс выступающий в роли Фасада (имеется ввиду паттерн "Фассад"), то есть класс, который рулит всем, что есть под капотом ДАЛ (запросы и прочее). К нему и надо прикрутить интерфейс ДАЛа.
Правильно ли я мыслю?

Далее. Не совсем понятно, в какой форме следует передавать данные из ДАЛ.
В ДАЛе хочется определить ДатаСет, который по идее и должен быть передан на слой представления. Но в каком виде? В неизменном? То есть как DataSet или же как DataTable? Или вообще в массивом? Не ясно.

Еще, думается мне, что в слое представления придется определять свой DataSet, а не создавать экземпляр того ДатаСета, который имеется в ДАЛ. Верно ли так поступать? Инкапсуляция же, слои не должны знать ничего друг о друге. Тем более, что ДатаСет, что в ДАЛе, скорее всего будет типизированым.

Итак, вынесу вопросы:
- Как примерно должен выглядеть интерфейс ДАЛа? Хочется увидеть пример.
- К чему прикручивать интерфейс в ДАЛе?
- В каком виде следует передавать данные на слой представления?
http://www.cyberforum.ru/csharp-beginners/thread1951554.html
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.12.2013, 08:54
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Организация Data Access Layer (C#):

Репозиторий в n-tier / 3-layer архитектуре
Передо мной стоит задача сделать проект с заменяемой ORM. Тестирую с nHibernate...

Определение доступных секторов DVD Dual Layer диска библиотекой IMAPI2.dll
Как известно на DVD DL диске содержится большее количество секторов, чем может...

Что лучше использовать System.Data.Linq или System.Data.sqlclient
что лучше использовать System.Data.Linq или System.Data.sqlclient для подкл к...

The conversion of a nvarchar data type to a datetime data type resulted in an out-of-range value
На моем компе программа работает, а на сервере получаю ошибкуThe conversion...

Ошибка: An unhandled exception of type 'System.Data.OracleClient.OracleException' occurred in system.data.oracleclient.dll
а вы что хотите получить, уважаемый? кол-во выбранных записей, или какое-то...

18
DataPlanner
153 / 183 / 49
Регистрация: 25.11.2013
Сообщений: 978
08.12.2013, 09:05 #2
1. Хочешь научиться прогать, забудь о датасетах и прочей ADO.NET ереси, данные в приложении должны быть только в коллекциях;
2. Интерфейс не очень удобно использовать в DAL новичку, научись пока использовать абстрактный класс, как фронт фасада;
0
Grishaco
435 / 359 / 100
Регистрация: 29.06.2010
Сообщений: 981
Записей в блоге: 1
08.12.2013, 11:11 #3
Цитата Сообщение от Void-87 Посмотреть сообщение
- Как примерно должен выглядеть интерфейс ДАЛа? Хочется увидеть пример.
Не претендую на оригинальность но можно так

Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/// <summary>
    /// Интерфейс контекста работы с базой данных
    /// </summary>
    public interface IDataContext : IDisposable
    {
        /// <summary>
        /// Время ожидания выполнения запроса
        /// </summary>
        int? CommandTimeout { get; set; }
 
        /// <summary>
        ///   Метод выполнения указанной хранимой процедуры с возвращением численного значения
        /// </summary>
        /// <param name = "procName">название хранимой процедуры</param>
        /// <param name = "parameters">список параметров</param>
        /// <returns>Значение возвращаемое процедурой</returns>
        T ExecuteScalarProcedure<T>(string procName, object parameters);
 
        /// <summary>
        /// Возвращает таблицу с данными при выполнении хранимой процедуры
        /// </summary>
        /// <param name="procedureName">Наименование хранимой процедуры</param>
        /// <param name="parameters">Параметры хранимой процедуры</param>
        /// <returns>Таблица с данными</returns>
        IEnumerable<TU> ExecuteProcedure<TU>(string procedureName, object parameters);
 
        /// <summary>
        /// Возвращает таблицу с описанием метаданных колонок
        /// </summary>
        /// <param name="procedureName">Наименование хранимой процедуры</param>
        /// <param name="parameters">Параметры хранимой процедуры</param>
        /// <returns>Таблица с данными</returns>
        DataTable GetSchemaTable(string procedureName, object parameters);
 
        /// <summary>
        /// Возвращает таблицу с данными при выполнении хранимой процедуры
        /// </summary>
        /// <param name="procedureName">Наименование хранимой процедуры</param>
        /// <param name="parameters">Параметры хранимой процедуры</param>
        /// <returns>Таблица с данными</returns>
        DataTable GetDataTable(string procedureName, object parameters);
 
        /// <summary>
        /// Метод выполнения указанной хранимой процедуры с возвращением численного значения
        /// </summary>
        /// <param name = "procName">название хранимой процедуры</param>
        /// <param name = "parameters">список параметров</param>
        /// <returns>Значение возвращаемое процедурой</returns>
        T ExecuteScalarSql<T>(string procName, object parameters);
 
        /// <summary>
        /// Возвращает объект указанного типа с указанным идентификатором, если идентификатор не указан, возвращается коллекция объектов указанного типа
        /// </summary>
        /// <typeparam name="TU">Тип объекта</typeparam>
        /// <param name="parameters">Динамический тип</param>
        /// <returns>Объект указанного типа с указанным идентификатором, если идентификатор не указан, возвращается коллекция объектов указанного типа</returns>
        IEnumerable<TU> Select<TU>(object parameters = null);
 
        /// <summary>
        /// Удаляет объект из базы данных
        /// </summary>
        /// <typeparam name="TU">Тип объектов</typeparam>
        /// <param name="obj">Экземпляр объекта, который необходимо сохранить</param>
        void Delete<TU>(TU obj);
 
        /// <summary>
        /// Сохраняет объект в базу данных
        /// </summary>
        /// <param name="obj">Экземпляр объекта, который необходимо сохранить</param>
        void Save<TU>(TU obj);
 
        /// <summary>
        /// Выполняет SQL код с заполнение коллекции объектов
        /// </summary>
        /// <param name="sqlText">SQL код</param>
        /// <param name="parameters">Список параметров</param>
        IEnumerable<TU> ExecuteSql<TU>(string sqlText, object parameters);
 
        /// <summary>
        /// Выполняет SQL код с заполнение коллекции объектов
        /// </summary>
        /// <param name="sqlText">SQL код</param>
        void ExecuteSql(string sqlText);
 
        /// <summary>
        /// Начинает транзакцию с уровнем изоляции по-умолчанию.
        /// </summary>
        void BeginTransaction();
 
        /// <summary>
        /// Начинает транзакцию с указанным уровнем изоляции <paramref name="isolationLevel"/>.
        /// </summary>
        void BeginTransaction(IsolationLevel isolationLevel);
 
        /// <summary>
        /// Подтверждает текущую открытую транзакцию.
        /// </summary>
        void CommitTransaction();
 
        /// <summary>
        /// Откатывает текущую открытую транзакцию.
        /// </summary>
        void RollbackTransaction();
 
        /// <summary>
        /// Выполняет хранимую процедуру
        /// </summary>
        /// <param name="procedureName">Наименование процедуры</param>
        /// <param name="parameters">Параметры процедуры</param>
        void ExecuteNonQueryProcedure(string procedureName, object parameters);
 
        /// <summary>
        /// Возвращает первый элемент из запроса или null
        /// </summary>
        /// <param name="parameters">Параметры запроса</param>
        /// <typeparam name="TU">Запрашиваемый тип объекта</typeparam>
        /// <returns>Возвращает первый элемент запроса или null</returns>
        TU FirstOrDefault<TU>(object parameters = null);
    }


Цитата Сообщение от Void-87 Посмотреть сообщение
- К чему прикручивать интерфейс в ДАЛе?
В смысле прикручивать?
Цитата Сообщение от Void-87 Посмотреть сообщение
- В каком виде следует передавать данные на слой представления?
Как удобно (все зависит от вашей фантазии) коллекции, датасеты, ключ - значение.
0
pincet
1300 / 887 / 120
Регистрация: 23.07.2010
Сообщений: 4,801
08.12.2013, 12:52 #4
Цитата Сообщение от DataPlanner Посмотреть сообщение
Хочешь научиться прогать, забудь о датасетах и прочей ADO.NET ереси, данные в приложении должны быть только в коллекциях;
смелое заявление
0
Grishaco
08.12.2013, 12:54
  #5

Не по теме:

Цитата Сообщение от pincet Посмотреть сообщение
смелое заявление
Все правильно, магия, бах бах и коллекция.

1
Void-87
2 / 2 / 1
Регистрация: 22.06.2012
Сообщений: 244
08.12.2013, 15:33  [ТС] #6
Цитата Сообщение от DataPlanner Посмотреть сообщение
1. Хочешь научиться прогать, забудь о датасетах и прочей ADO.NET ереси, данные в приложении должны быть только в коллекциях;
2. Интерфейс не очень удобно использовать в DAL новичку, научись пока использовать абстрактный класс, как фронт фасада;
1. Почему же? ДатаСеты мне кажутся очень удобной вещью.
2. Например как?

Добавлено через 46 секунд
Цитата Сообщение от Grishaco Посмотреть сообщение
В смысле прикручивать?
Где, в каком классе реализовывать?

Добавлено через 1 минуту
Цитата Сообщение от Grishaco Посмотреть сообщение
Как удобно (все зависит от вашей фантазии) коллекции, датасеты, ключ - значение.
Имею ввиду, как поступают большие дядьки при написании реальных приложений использующих ADO.NET
0
Grishaco
435 / 359 / 100
Регистрация: 29.06.2010
Сообщений: 981
Записей в блоге: 1
08.12.2013, 16:32 #7
Цитата Сообщение от Void-87 Посмотреть сообщение
Где, в каком классе реализовывать?
Ну если есть интерфейс, то дело за классом не станет. Делаете реализацию, пока для DataTable, это будет самый низкий уровень (хотя есть еще ниже). Например так (код не относится к ранее показанному интерфейсу)

Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
public class DataContext
    {
        public void ExecuteNonQuery(string query, List<SqlParameter> listParams, int commandTimeout)
        {
            using (var connection = new SqlConnection(Settings.Default.ConnectionString))
            {
                using (var cmd = new SqlCommand(query, connection))
                {
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandText = query;
                    cmd.CommandTimeout = commandTimeout;
                    cmd.Parameters.AddRange(listParams.ToArray());
                    connection.Open();
                    cmd.ExecuteNonQuery();
                    connection.Close();
                }
            }
        }
 
        public void ExecuteNonQueryStoredProcedure(string procName, List<SqlParameter> listParams, int commandTimeout)
        {
            using (var connection = new SqlConnection(Settings.Default.ConnectionString))
            {
                using (var cmd = new SqlCommand(procName, connection))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = procName;
                    cmd.CommandTimeout = commandTimeout;
                    cmd.Parameters.AddRange(listParams.ToArray());
                    connection.Open();
                    cmd.ExecuteNonQuery();
                    connection.Close();
                }
            }
        }
 
        public DataTable ExecuteQuery(string query, List<SqlParameter> listParams, int commandTimeout)
        {
            using (var connection = new SqlConnection(Settings.Default.ConnectionString))
            {
                using (var cmd = new SqlCommand(query, connection))
                {
                    cmd.CommandType = CommandType.Text;
                    cmd.CommandText = query;
                    cmd.CommandTimeout = commandTimeout;
                    cmd.Parameters.AddRange(listParams.ToArray());
                    connection.Open();
                    var dt = new DataTable();
                    dt.Load(cmd.ExecuteReader());
                    return dt;
                }
            }
        }
 
        public DataTable ExecuteStoredProcedure(string procName, List<SqlParameter> listParams, int commandTimeout)
        {
            using (var connection = new SqlConnection(Settings.Default.ConnectionString))
            {
                using (var cmd = new SqlCommand(procName, connection))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = procName;
                    cmd.Parameters.AddRange(listParams.ToArray());
                    cmd.CommandTimeout = commandTimeout;
                    connection.Open();
                    var dt = new DataTable();
                    dt.Load(cmd.ExecuteReader());
                    return dt;
                }
            }
        }
 
        public int ExecuteScalarQuery(string procName, List<SqlParameter> listParams, int commandTimeout)
        {
            using (var connection = new SqlConnection(Settings.Default.ConnectionString))
            {
                using (var cmd = new SqlCommand(procName, connection))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = procName;
                    cmd.Parameters.AddRange(listParams.ToArray());
                    cmd.CommandTimeout = commandTimeout;
                    connection.Open();
                    object value = cmd.ExecuteScalar();
                    int result;
                    if (value == DBNull.Value || value == null)
                    {
                        result = -1;
                    }
                    else
                    {
                        result = (int) value;
                    }
 
                    connection.Close();
                    return result;
                }
            }
        }
 
        public int ExecuteScalarStoredProcedure(string procName, List<SqlParameter> listParams, int commandTimeout)
        {
            using (var connection = new SqlConnection(Settings.Default.ConnectionString))
            {
                using (var cmd = new SqlCommand(procName, connection))
                {
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = procName;
                    cmd.Parameters.AddRange(listParams.ToArray());
                    cmd.CommandTimeout = commandTimeout;
                    connection.Open();
                    object value = cmd.ExecuteScalar();
                    int result;
                    if (value == DBNull.Value || value == null)
                    {
                        result = -1;
                    }
                    else
                    {
                        result = (int) value;
                    }
 
                    connection.Close();
                    return result;
                }
            }
        }
    }


В целом каркас готов, что дальше? Дальше вы начинаете с ним работать, но в один момент понимаете что удобнее будет работать с объектами (особенно после вкуривания всех прелестей биндинга). Дальше вы создаете еще одну прослойку поверх первой (еще кучу атрибутов), которая переводит DataRow в объект и возвращает коллекцию объектов. Потом вы понимаете что чтение сначала в DataTable, потом перевод в объекты слишком тормознутый вариант и начинаете работать уже с DbReader. И т.д.

Пример заполнения объекта из DataRow

Кликните здесь для просмотра всего текста
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/// <summary>
        /// Заполняет объект значениями из строки данных
        /// </summary>
        /// <param name="drAttiribute">Строка с данными</param>
        /// <param name="classObject">Объект свойства которого необходимо заполнить</param>
        /// <param name="fieldInformation">Информация поля класса</param>
        /// <param name="propertyInformation">Информация свойства класса</param>
        public static void FillObjectFromDataRowValues(this DataRow drAttiribute, object classObject,
                                                       List<FieldInformation> fieldInformation,
                                                       List<PropertyInformation> propertyInformation)
        {
            foreach (DataColumn c in drAttiribute.Table.Columns)
            {
                int columnIndex = drAttiribute.Table.Columns.IndexOf(c);
                object value = drAttiribute[columnIndex];
               
                foreach (PropertyInformation info in propertyInformation)
                {
                    if (FillAttributeProperty(classObject, value, info.PropertyInfo, c.ColumnName,
                                              info.SqlParameterAttributes))
                        break;
                    //if (FillProperty(classObject, value, info.PropertyInfo, c.ColumnName)) break;
                }
            }
        }
 
/// <summary>
        /// Устанавливает значения свойства объекта
        /// </summary>
        /// <param name="classObject">Объект</param>
        /// <param name="value">Значение</param>
        /// <param name="info">Атрибуты свойства</param>
        /// <param name="columnName">Название колонки</param>
        /// <param name="fta">Атрибуты</param>
        /// <returns>true - значение установленно</returns>
        private static bool FillAttributeProperty(object classObject, object value, PropertyInfo info,
                                                  string columnName, SqlParameterAttribute[] fta)
        {
            if (fta.Length == 0) return false;
 
            if (fta[0].IsOnlyForWrite) return false;
 
            if (fta[0].NameColumn != columnName) return false;
 
            try
            {
                info.SetValue(classObject, ValueIsDbNull(value) ? null : value, null);
            }
            catch (ArgumentException exception)
            {
                throw new ArgumentException(exception.Message, columnName, exception.InnerException);
            }
 
            return true;
        }
 
/// <summary>
        /// Метод проверки значения на SQL NULL
        /// </summary>
        /// <param name="value">Значение аргумента</param>
        /// <returns>True - значение равно, False - значение не равно</returns>
        private static bool ValueIsDbNull(object value)
        {
            return value == DBNull.Value;
        }


Цитата Сообщение от Void-87 Посмотреть сообщение
Имею ввиду, как поступают большие дядьки при написании реальных приложений использующих ADO.NET
Я так думаю им обычно лень и они используют, в зависимости от задачи, все прелести ADO.NET в том числе и для работы с XML.
0
freeba
Неадекват
1222 / 1024 / 192
Регистрация: 02.04.2010
Сообщений: 2,356
Записей в блоге: 2
Завершенные тесты: 2
08.12.2013, 16:57 #8
Цитата Сообщение от Void-87 Посмотреть сообщение
как поступают большие дядьки при написании реальных приложений использующих ADO.NET
Если нужно отвязаться от слоя данных, то создается интерфейс содержащий все методы для работы с базой и соответственно на каждый слой данных делается своя реализация этого интерфейса. А связывание нужного слоя с логикой можно реализовать либо вручную, либо через DI (для настоящих лентяев). Тогда работа с бд (или чего там будет выступать в роли хранилища данных) сводится к подобной абстракции (используется ninject):
C#
1
2
3
4
5
6
7
[Inject]
        public IRepository Repository { get; set; }
 
        public List<User> GetAllUsers()
        {
            return Repository.Users.ToList();
        }
Привязка нужной реализации:
C#
1
kernel.Bind<IRepository>().To<SQLRepository>().InRequestScope();
0
serefa
50 / 43 / 4
Регистрация: 07.10.2010
Сообщений: 95
09.12.2013, 14:54 #9
Еще можно добавить, что часто возле DAL создают трансляторы. Это статический класс, содержащий методы конвертации одних данных в другие.
Типа ConvertToXml, ConvertFromXml, ConvertToDataTable
Делаеся это для того, что б не тяуть специфические зависимости из ДАЛ в весь проект.
К примеру что б адо нет со своими дататайблами оставался тольо в дале.
Что б при изменении веб-сервиса пришлось перекомпилировать только дал, а не весь проект.
И что б не было .ToList(); в
C#
1
2
3
4
5
6
7
[Inject]
        public IRepository Repository { get; set; }
 
        public List<User> GetAllUsers()
        {
            return Repository.Users.ToList();
        }
0
freeba
Неадекват
1222 / 1024 / 192
Регистрация: 02.04.2010
Сообщений: 2,356
Записей в блоге: 2
Завершенные тесты: 2
09.12.2013, 15:48 #10
Цитата Сообщение от serefa Посмотреть сообщение
Еще можно добавить, что часто возле DAL создают трансляторы. Это статический класс, содержащий методы конвертации одних данных в другие.
Месье знает толк... Организация отдельного слоя данных подразумевает, что могут использоваться несколько источников, но с точки зрения логики источник должен быть один - следовательно ни о каких статических классах занимающихся конвертацией речи быть не может. Каждый слой предоставляет нам уже подготовленные данные.

Цитата Сообщение от serefa Посмотреть сообщение
И что б не было .ToList(); в
ToList вызывается потомучто метод возвращает список, а вобще Users объявлен как IQueryable<User>.
0
serefa
50 / 43 / 4
Регистрация: 07.10.2010
Сообщений: 95
09.12.2013, 17:41 #11
Правильно. Каждый слой предоставляет нам уже подготовленные данные.
Вся проблема в том, что данные могут приходить в разных форматах.
DataTable oт Ado.Net
IQueryable oт EF
xml oт java вебсервисов.
прокси-классы от WCF
И все это нужно как то привести к единому интерфейсу.
Вот возьмем ваш пример. Заказчик говорит - даные будешь получать от такого веб-сервиса. Вот его адрес и вот структура xml. Что будешь дельть со своим IQueryable<User>? Писать конвертер IEnumerableToIQueryable и ругать себе не хорошими словами, так как IQueryable ни к селу ни к городу.
0
DataPlanner
153 / 183 / 49
Регистрация: 25.11.2013
Сообщений: 978
09.12.2013, 19:28 #12
Интерфейс IQueryable мощная штука
0
freeba
Неадекват
1222 / 1024 / 192
Регистрация: 02.04.2010
Сообщений: 2,356
Записей в блоге: 2
Завершенные тесты: 2
09.12.2013, 19:57 #13
Цитата Сообщение от serefa Посмотреть сообщение
Что будешь дельть со своим IQueryable<User>? Писать конвертер IEnumerableToIQueryable и ругать себе не хорошими словами, так как IQueryable ни к селу ни к городу.
Если речь идет о работе с количеством объектов более 1000, то буду. Лучше потратить лишнее время на этапе разработки, чем потом когда код уйдет в продакшн - искать в каком месте проседает производительность и один черт переписывать IEnumerable на IQueryable, только уже в режиме аврала.

Добавлено через 2 минуты
Цитата Сообщение от serefa Посмотреть сообщение
DataTable oт Ado.Net
IQueryable oт EF
прокси-классы от WCF
Эти ребята поддерживают IQueryable или из коробки, или с незначительными допилами.
0
DataPlanner
153 / 183 / 49
Регистрация: 25.11.2013
Сообщений: 978
09.12.2013, 20:34 #14
Цитата Сообщение от serefa Посмотреть сообщение
Писать конвертер IEnumerableToIQueryable
Звучит, как бред, это разные веши, почитайте доки

Добавлено через 6 минут
The IQueryable<(Of <(T>)>) interface enables queries to be polymorphic. That is, because a query against an IQueryable data source is represented as an expression tree, it can be executed against different types of data sources.
А если добавить динамическое генерацию лямбда-выражений... Что-нибудь типа такого:
C#
1
2
3
4
5
6
7
8
9
10
private static Expression Convert(Expression expression)
        {
            if (expression.NodeType == ExpressionType.Constant)
            {
                return expression;
            }
            LambdaExpression lambda = Expression.Lambda(expression);
            Delegate lambdaDelegate = lambda.Compile();
            return Expression.Constant(lambdaDelegate.DynamicInvoke(null), expression.Type);
        }
0
serefa
50 / 43 / 4
Регистрация: 07.10.2010
Сообщений: 95
09.12.2013, 21:06 #15
Прочитай весь мой вопрос.
У нас есть метод возврощающий IQueryable. В этом методе мы обращаемся к серверу и получаем xml c коллекцией.
Эта коллекция будет распарщенна в какой нибудь лист, масив и тд. - то есть в IEnumerable. А теперь нам нужно эту штуку преобразовать(??) в IQueryable. Зачем? Что нам это даст? Особенно используя интерфейс, который большинство не понимает.

То же самое касается WCF и DataTable.
Зачем вытаскивать наружу специфичесие реализациии конкретных технологий?
0
Void-87
2 / 2 / 1
Регистрация: 22.06.2012
Сообщений: 244
10.12.2013, 13:40  [ТС] #16
Граждане холиварствующие, я понял вас правильно, с ДАЛА нежно возвращать данные в виде простых типов типа списков и массивах, которые понимают все. В DataTable и тем более DataSet - привязка к АДО.НЕТ
0
Grishaco
10.12.2013, 14:18
  #17

Не по теме:

Цитата Сообщение от Void-87 Посмотреть сообщение
Граждане холиварствующие, я понял вас правильно, с ДАЛА нежно возвращать данные в виде простых типов типа списков и массивах, которые понимают все. В DataTable и тем более DataSet - привязка к АДО.НЕТ
Какой то противоречивый ответ или вопрос.

0
Void-87
2 / 2 / 1
Регистрация: 22.06.2012
Сообщений: 244
10.12.2013, 14:39  [ТС] #18
Опечатался так опечатался. Нежно надо возвращать, ага.

Итак, с Data Access Layer нужно возвращать простые типы (List, Array)? Потому что тогда нет привязки к технологии ADO.NET?
0
freeba
Неадекват
1222 / 1024 / 192
Регистрация: 02.04.2010
Сообщений: 2,356
Записей в блоге: 2
Завершенные тесты: 2
10.12.2013, 14:42 #19
Void-87, нет, вы поняли неправильно. В сторону логики должны смотреть интерфейсы обеспечивающие, как простоту доступа, так и достаточную производительность. Если вам хочется использовать DataSet - пожалуйста, но все слои данных должны будут обеспечивать работоспособность DataSet.

Уважаемый serefa, немного передергивает ситуацию в сторону идеализма. Да, можно на каждый чих написать свой метод, который вернет "простой" тип, но на практике это используется чуть реже, чем никогда - какой смысл писать, например, хранимую процедуру если она будет вызываться раз в неделю? Гораздо проще и быстрее сделать вызов LinqToSql, тем более, что все основные поставщики данных это поддерживают.
0
10.12.2013, 14:42
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
10.12.2013, 14:42
Привет! Вот еще темы с решениями:

Имя типа или пространства имен "Data" отсутствует в пространстве имен "Data"
Имя типа или пространства имен &quot;Data&quot; отсутствует в пространстве имен &quot;Data&quot;...

Data access layer для с++
какую библиотеку можете посоветовать, и почему именно ее?

Можно ли считать это Data Access Layer?
Делал задние: простое клиент-серверное приложение с использованием вебсервиса....

Как сделать полосу прокрутки в теге <layer></layer>?
Браузер NN. Нужно сделать полосу прокрутки слоя, как? Желательно показать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
19
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru