Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[13.58.113.193] |
|
Страницы: (2) [1] 2 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Если объект, вызываемый через Remouting, содержит член типа OleDbConnection, то при вызове выскакивает исключение: "Из-за ограничений по соображениям безопасности тип System.Runtime.Remoting.ObjRef недоступен"
ВОПРОС РЕШЕН. Похоже, TypeFilterLevel=TypeFilterLevel.Full; помог. |
Сообщ.
#2
,
|
|
|
Jupiter, здается мне, если через ремотинг перекидывается объект подключения к базе данных - в приложении серьезные проблемы с архитектурой
|
Сообщ.
#3
,
|
|
|
Передавать объект подключения к базе через Remoting - не плохая идея, если у меня база реализована в виде MS Access (.mdb) на сервере (служба), а клиент подключается к базе удаленно. Это должно позволить мне избежать использования SQL сервера. (Ну вот так у нас получается исторически).
Проблема, как оказаласть, не решена. Когда я конкретно начинаю использовать это соединение, то получаю исключение: private void YYYY(OleDbConnection conn) { DataTable customerTable = new DataTable(); OleDbCommand myCmd = new OleDbCommand(); DataSet ds = new DataSet(); try { if (conn.State == ConnectionState.Closed) conn.Open(); myCmd.Connection = conn; myCmd.CommandText = "SELECT * FROM trModules"; OleDbDataAdapter da = new OleDbDataAdapter(myCmd); OleDbCommandBuilder db = new OleDbCommandBuilder(da); DataTable dt = new DataTable(); ///////////////////// da.Fill(dt); // Все, приехали... ///////////////////// } // ... } Вот такое исключение: -------------------------------------------------------------------------------------------------------------------------- Failed to connect to data source -- System.Runtime.Remoting.RemotingException: Отказано в разрешении: удаленный вызов статических методов и методов, не являющихся общими. Server stack trace: в System.Runtime.Remoting.Channels.ChannelServices.DispatchMessage(IServerChannelSinkStack sinkStack, IMessage msg, IMessage& replyMsg) Exception rethrown at [0]: в System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) в System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) в System.Data.OleDb.OleDbConnection.CheckStateOpen(String method) в System.Data.OleDb.OleDbCommand.ValidateConnection(String method) в System.Data.OleDb.OleDbCommand.ValidateConnectionAndTransaction(String method) в System.Data.OleDb.OleDbCommand.ExecuteReaderInternal(CommandBehavior behavior, String method) в System.Data.OleDb.OleDbCommand.ExecuteReader(CommandBehavior behavior) в System.Data.OleDb.OleDbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior) в System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior) в System.Data.Common.DbDataAdapter.Fill(DataTable[] dataTables, Int32 startRecord, Int32 maxRecords, IDbCommand command, CommandBehavior behavior) в System.Data.Common.DbDataAdapter.Fill(DataTable dataTable) в XXX.fModules.YYYY(OleDbConnection conn) в D:\Projects\XXX\fModules.cs:строка 65 |
Сообщ.
#4
,
|
|
|
Цитата Jupiter @ Передавать объект подключения к базе через Remoting - не плохая идея, если у меня база реализована в виде MS Access (.mdb) на сервере (служба), а клиент подключается к базе удаленно. Идея не хорошая. Мне кажется, что ты не совсем правильно понимаешь концепцию. Хорошая идея, когда сервер общается с БД, а клиент вызывает методы сервера, для получения и отпраки данных. |
Сообщ.
#5
,
|
|
|
Да, мне это и нужно. Подскажи, если не в лом, (в общих словах) как реализовать обмен данными между клиентом и сервером. Я расчитывал, что (грубо говоря) от клиента к серверу будут идти SQL-инструкции, а от сервера к клиенту - DataSet'ы. Но похоже, с передачей ДатаСетов - напряженка. Что тогда? Массивы?
Спасибо. |
Сообщ.
#6
,
|
|
|
Jupiter, вариантов много.
1. Простой и довольно эффективный использовать DataTabel как трансферный объект. Достоинства простота реализации, довольно высокая скорость передачи данных. В данном случае по Фаулеру ты используешь "шлюз доступа к таблице". Имеем например таблицу Persons, а в коде класс Persons который по сути есть врапером над DataTable и имеет методы по инициализации его из БД и обновлению данных в нем. Громадный недостаток отстутствие типизации. 2. Использовать коллекции. Это обычно более правильный в сложных проектах путь. В данном случае ты имеешь класс Person представляющий абстракцию строки из таблицы в БД (шлюз доступа к строке), соответственно коллекция (List<Person>) таких объектов есть представление таблицы. Паралельно пишешь контролеры, которые сводишь например в репозиторий. С их помощью ты будешь выбирать данные. Ответственность на сохранение и обновление объектов обычно ложится на сами шлюзы. Достоинство, код обычно более точно характеризует то, что ты реально программируешь и соответствует предметной области. Код строго типизирован и с ним легко работать клиенту. Из недостатков, намного больше писанины. Поэтому в таких случаях обычно используют объектно реляционный преобразователь, который твои объекты отображает на БД и обратно. Ну и на последок, нужно всегда помнить, что распределенное приложение очень требовательно к объему передаваемых по сети данных, их нужно минимизировать. Лично я обычно использую фасадный класс, который по возможности имеет простой интерфейс для удаленного взаимодействия клиента с сервером. Методы которого возвращают DTO (Data Transfer Object) если смотреть на вариант 1 и принимает по возможности максимально простой список аргуметов. И не забывай, что клиенту никогда не понадобится 1000 000 записей |
Сообщ.
#7
,
|
|
|
Понятно, спасибо. Мне понравился первый метод. Только не ясно что такое "по Фаулеру".
Цитата Имеем например таблицу Persons, а в коде класс Persons который по сути есть врапером над DataTable Как хранятся записи таблицы в этом классе? |
Сообщ.
#8
,
|
|
|
Цитата Jupiter @ Не понятны слова "по Фаулеру" Есть книга одна умная им написаная где он пытался обобщить опыт в виде шаблонов для корпоративніх приложений. Цитата Jupiter @ "врапером" обвертка над чем либо. Цитата Jupiter @ Как я понял, класс Persons представляет ВСЮ таблицу, а не одну запись. Как в нем хранятся записи? В виде объекта DataTable выглядеть в примитивном виде может так: public class Persons { private DataTable _table; private DbConnection _connection; private DbDataAdapter _adapter; public Persons() { // инициализация объектов } public DataTable GetData() { // заполняем-возвращаем } public void Update(DataTable changedData) { // обновляем записи в БД. } ... } При этом логичным выглядит вынести общую логику в абстрактный класс, возможно с использованием Generic Далее все такие классы сводятся к единому контексту который может содержать их коллекцию чем-то похоже на DataSet, но при этом иметь методы вроде SubminChanged .. или явные методы по получению наборов записей из классов аналогичных Persons. Вариантов тьма. Потом ты используешь эти классы уже в своем фасаде, который делегирует вызовы, уже конкретным шлюзам или контексту, там же можно расположить и различные бизнесс правила. Вообще вариант решения в лоб. Так часто делают, когда проекты не большие или ориентированы исключительно на работу с данными. Добавлено Цитата Jupiter @ Только не ясно что такое "по Фаулеру". http://www.books.ru/shop/books/156126 Есть просто много авторов и у каждого из них часто своя терминология. |
Сообщ.
#9
,
|
|
|
Все теперь ясно. Спасибо. Фишка в том, что через Remoting вместо объекта Connection мы передаем DataTable Попробуем...
|
Сообщ.
#10
,
|
|
|
Да, действительно, DataTable успешно передается через Remoting!!! (не знаю уж почему OleDbConnection не передается, а DataTable - передается). Вот такой примитивный метод, реализованный в Remoting-классе, уже позволяет удаленно извлекать данные по sql-запросу:
public DataTable GetDataTable(string sql) { OleDbCommand myCmd = new OleDbCommand(sql, _domainDbConn); OleDbDataAdapter da = new OleDbDataAdapter(myCmd); OleDbCommandBuilder db = new OleDbCommandBuilder(da); DataTable dt = new DataTable(); da.Fill(dt); return dt; } |
Сообщ.
#11
,
|
|
|
Цитата Jupiter @ такой примитивный метод, реализованный в Remoting-классе, уже позволяет удаленно извлекать данные по sql-запросу Надеюсь ты так не станешь делать в своем приложении, а код привел исключительно для демонстрации |
Сообщ.
#12
,
|
|
|
Цитата Ну да, там должно быть все упрятано внутрь, под предметную область. СПАСИБО! Надеюсь ты так не станешь делать в своем приложении, а код привел исключительно для демонстрации |
Сообщ.
#13
,
|
|
|
Добрый день.
Также прошу помощи, т.к. столкнулся с такой же "проблемой" и не совсем понятна суть предлагаемого решения Итак, есть клиент сервер в режиме синглетон БД клиент запрашивает получить, к примеру, спискок сотрудников. Если я правильно понял, то правильное решение -- сделать "обертку" для этих данных -- для чего juice как пример привел класс Person. Вопрос -- как и где вызывать "создание", получение данных. понятно, что на сервере. мне не совсем ясна реализация т.е. Клиент вызывает remoteobject.GetPerson(); или Person prs = new Person(); prs.GetData(); но как тогда быть с коннекшеном, который требуется для получения данных? как правильно? Сорри, может за сумбурное вопрос, но пли -- нид хелп |
Сообщ.
#14
,
|
|
|
Shogunx, у удаленного объект реализует интерфес:
List<Person> AllPerson(); Person GetPersonForId(long id); ... List<Peroson> persons = remoteobject.AllPerson(); Person person = remoteObject.PersonForId(long id); Person person = new Person() remoteObject.AddPerson(Person person) //часто предпочтительней передать просто список парамметров, а конструировать Person на сервере Теперь о том, что делает сервер. Рассмотрим пример метода: public List<Person> AllPerson() { return Database.PersonProvider.GetAll(); } А вотстатическое свойство PersonProvider объекта Database возвращает ссылку на экземпляр какого нибудь PersonController, может быть реализовано примерно так: public class PersonController : EntityController { public List<Person> GetAll() { Выбыраем их БД данные и возврящаем клиенту. } } При этом объект вроде EntityController и должен содержать объект Connection и прочую общую ерунду. |
Сообщ.
#15
,
|
|
|
juice, спасибо большое за помощь, более менее стало приходит озарение , но все-таки можно тебя еще помучать
итак, я накидал вот такой код public class EntityController { private SqlConnection sqlConnection = new SqlConnection(); public string BuildConnectionString() { return null; } public EntityController() { } } public class PersonController : EntityController { public DataTable GetList() { return null; } public PersonController() { } } public class Databases { public static PersonController persons; public Databases() { } } public interface IRemoteObject { DataTable GetAllPerson(); } public class RemoteObject : MarshalByRefObject, IRemoteObject { private Databases rData = new Databases(); public DataTable GetAllPerson() { rData.persons.GetList(); } } Все это реализовано в отдельно сборке, как ты и рекомендовал, доступно той и другой стороне. Далее, клиент подключается к серверу, который уже "держит" соединение с БД. Соответственно на сервере есть уже созданный объект EntityController. Но вот здесь по коду возникает затык, а именно в rData.persons.GetList(); Сорри, если написал бред ) |