Что почитать о том, как создать многопользовательскую программу WPF C#?

Хочу написать клиент-серверное приложение WPF C# SQL Server. К сожалению опыта в этой части, у меня нет совершенно, по этому наткнулся на грабли.

Итак, к программе... Пользователь с правами администратора должен регистрировать новых пользователей и наделять их правами доступа к функциональной части программы (добавление, чтение, редактирование, удаление). Ни как не могу найти хоть примерно похожую архитектуру БД. Так же не понятно как в этой части БД должна взаимодействовать с различными элементами управления программы. Будьте добры, подскажите какую-нибудь статью-пример по этому вопросу.

Взаимодействие с БД идет через веб-сервис, и WPF приложение вообще не знает про базу, работая с моделью.

А ссылочкой не поделитесь на мануал по этому решению?

Автоматически получаем многопользовательское приложение, к веб-сервису можно будет подключить сколько угодно WPF клиентов.


Если я правильно понимаю, для этих целей нужно использовать фреймворк. Подскажите фреймворк по проще, для начинающего.
  • Вопрос задан
  • 6271 просмотр
Пригласить эксперта
Ответы на вопрос 2
DmitriyEntelis
@DmitriyEntelis
Думаю за деньги
Поделюсь прямо готовым примером

1) Надо как то хранить в БД права пользователя
Вводим понятие "роль" - это некое тривиальное право доступа к конкретному разделу (например user_view, user_edit, user_delete).
CREATE TABLE `role` (
 `role_title` varchar(255) NOT NULL COMMENT 'Роль',
 `role_title_description` text NOT NULL COMMENT 'Описание роли',
 PRIMARY KEY (`role_title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Роли пользователей';

Роли объединяются в группы (администраторы, модераторы, итд)
CREATE TABLE `group` ( 
 `group_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID группы', 
 `name` text NOT NULL COMMENT 'Имя группы',  
  PRIMARY KEY (`group_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Группы пользователей';

CREATE TABLE `xref_group_role` (  
`group_id` int(11) NOT NULL,  
`role_title` varchar(255) NOT NULL,  
PRIMARY KEY (`group_id`,`role_title`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Связь групп и ролей';

Ну и пользователи привязаны к группам
CREATE TABLE `xref_user_group` (  
`user_id` int(11) NOT NULL,  
`group_id` int(11) NOT NULL,  
PRIMARY KEY (`group_id`,`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Связь пользователей и групп'


2) Когда пользователь авторизуется - получаем список его ролей
SELECT 
	distinct `role`.`role_title`
FROM 
	`xref_user_group`
JOIN `xref_group_role`
	ON `xref_user_group`.`group_id` = `xref_group_role`.`group_id`
JOIN `role`
	ON `xref_group_role`.`role_title` = `role`.`role_title`
WHERE
	`xref_user_group`.`user_id` = 123


3) В рамках данного примера подразумевается что все роли исключительно "разрешительные". Если у пользователя есть роль - он может совершать соответствующее действие. Нет - не может.
Соответственно в логике приложения, когда пользователь пытается совершить какое то действие - просто проверяем наличие у него роли.

Фуф)

UPD
Спасибо, большое!
Только не совсем понятно как это должно взаимодействовать например с меню. Например есть меню Правка -> Добавить, Изменить, Удалить. Если у пользователя есть права на добавление и изменение но нет на удаление, как сделать что бы пункт меню "Удалить" был не активен?

Я под десктоп последний раз кодил лет 12 назад на Visual Basic (еще не .net) , но тем не менее:
У вас должен быть код который создает это меню. В этот код вставляем все проверки ролей.
Если кода меню нет (вы собрали меню через конструктор), то нужно написать код который выполняется скажем при загрузке формы, смотрит на роли текущего пользователя и соответственно включает/выключает пункты меню.
Ответ написан
Комментировать
Ogoun
@Ogoun
Programmer
Напишу не про базу. а про общую часть. Здесь хорошо бы разделить на слои приложение, UI (WPF приложение), веб-сервис, и БД. Соответственно все взаимодействие с БД идет через веб-сервис, и WPF приложение вообще не знает про базу, работая с моделью. На уровне веб-сервиса реализуется авторизация, и определяется набор операций доступных пользователю (например, админ может все, оператор только операции чтения вызывать). Автоматически получаем многопользовательское приложение, к веб-сервису можно будет подключить сколько угодно WPF клиентов. (соответственно не только WPF при необходимости).

В одной из своих реализаций, где набор данных ограничивался до 100 мегабайт, я вообще использовал SQL Compact Edition, запись(редкая в проекте операция) велась в базу, при запуске веб-сервиса все данные помещались в оперативную память из базы и при чтении данных к диску обращений не было.

Создание веб-службы
Еще пример

Создание прокси на веб-службу
Хотя мне нравится делать прокси вручную, больше гибкости:
[WebServiceBinding(Namespace = "SampleWebService")]
    public class SampleWebServiceProxy : SoapHttpClientProtocol
    {
        public SampleWebServiceProxy(string serviceUrl)
        {
            Url = serviceUrl;
            UseDefaultCredentials = true;
        }

        protected override WebRequest GetWebRequest(Uri uri)
        {
            WebRequest webRequest = base.GetWebRequest(uri);
            ((HttpWebRequest)webRequest).ServicePoint.ConnectionLeaseTimeout = 0;
            return webRequest;
        }

        [SoapDocumentMethod("GetUser",
            Action = "http://domain/GetUser",
            Use = System.Web.Services.Description.SoapBindingUse.Literal,
            ParameterStyle = SoapParameterStyle.Wrapped)]
        [WebMethod(MessageName = "", Description = "")]
        public User GetUser(Guid id)
        {
            return InvokeMethodWithResult("GetUser", id);
        }
		
		[SoapDocumentMethod("UpdateUser",
            Action = "http://domain/UpdateUser",
            Use = System.Web.Services.Description.SoapBindingUse.Literal,
            ParameterStyle = SoapParameterStyle.Wrapped)]
        [WebMethod(MessageName = "", Description = "")]
        public void UpdateUser(User user)
        {
            return InvokeMethod("UpdateUser", user);
        }

        private object InvokeMethodWithResult(string methodName, params object[] args)
        {
            return Invoke(methodName, args ?? new object[] { }).FirstOrDefault();
        }

        private void InvokeMethod(string methodName, params object[] args)
        {
            Invoke(methodName, args ?? new object[] { }).FirstOrDefault();
        }
    }


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

Получаем следующую схему:
29347e299155457794990fe5883ba88a.png
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы