Напишу не про базу. а про общую часть. Здесь хорошо бы разделить на слои приложение, 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();
}
}
Собственно все. В комментарии выше показаны примеры для работы с базой. Использование фреймворков тут нецелесообразно, таблиц немного, проще будет вручную замапить на объекты.
Получаем следующую схему: