Простой дизайн базы данных и LINQ - PullRequest
1 голос
/ 11 мая 2010

У меня очень мало опыта в проектировании баз данных, и теперь я хочу создать очень простую базу данных, которая делает то же самое, что ранее у меня была в xml. Вот XML:

<services>
  <service type="writing">
    <small>125</small>
    <medium>100</medium>
    <large>60</large>
    <xlarge>30</xlarge>
  </service>
  <service type="analysis">
    <small>56</small>
    <medium>104</medium>
    <large>200</large>
    <xlarge>250</xlarge>
  </service>
</services>

Теперь я хотел создать то же самое в базе данных SQL и начал делать это (надеюсь, что с форматами все в порядке, но вы получите суть, четыре столбца и две строки):

> ServiceType Small Medium Large
> 
> Writing       125    100    60
> 
> Analysis       56    104   200

Это не сработало, так как я тогда хотел использовать LINQ, чтобы выбрать, скажем, Большое значение для записи (60). Но я не мог использовать LINQ для этого (насколько я знаю) и использовать переменную для размера (см. Параметры в методе ниже). Я мог бы сделать это, только если бы у меня был столбец типа «Размер», где значения «Маленький», «Средний» и «Большой» были бы значениями. Но это тоже не совсем правильно, потому что тогда я получу несколько строк с ServiceType = Writing (3 в данном случае, по одному для каждого размера), и то же самое для Analysis. И если бы мне пришлось добавить больше типов обслуживания, я бы сделал то же самое. Просто повторяющийся ... Есть ли какой-нибудь умный способ сделать это, используя отношения или что-то?

Используя второй дизайн выше (хотя и не очень), я мог бы использовать следующий LINQ для выбора значения с параметрами, отправляемыми в метод:

protected int GetHourRateDB(string serviceType, Size size)
{
  CalculatorLinqDataContext context = new CalculatorLinqDataContext();
  var data = (from calculatorData in context.CalculatorDatas
        where calculatorData.Service == serviceType && calculatorData.Size == size.ToString()
        select calculatorData).Single();
  return data.Hours;
}

Но если есть другой лучший дизайн, не могли бы вы также описать, как сделать тот же выбор, используя LINQ с этим дизайном?

Пожалуйста, имейте в виду, что я новичок в проектировании баз данных, поэтому, пожалуйста, будьте максимально понятны и педагогичны: -)

Спасибо!

Андерс

Ответы [ 2 ]

2 голосов
/ 11 мая 2010

Вы можете использовать свой первый метод и сделать что-то вроде этого:

protected int GetHourRateDB(string serviceType, Size size)
{
    using (CalculatorLinqDataContext context = new CalculatorLinqDataContext())
    {
        var data =
            (from calculatorData in context.CalculatorDatas
            where calculatorData.Service == serviceType
            select calculatorData).Single();

        switch (size) {
            case Small:
                return data.Small;
            case Medium:
                return data.Medium;
            case Large:
                return data.Large;
            default:
                // Error handling
         }
     }
}

Ваш второй метод также будет работать, но если вы знаете, что всегда будет ровно три размера для всех элементов и что они всегда будут называться Small, Medium и Large, то с помощью первых методов вы можете жестко закодировать их схемы и получить базу данных, чтобы обеспечить ее выполнение для вас.

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

1 голос
/ 11 мая 2010

Если вы хотите использовать перечисление для выбора нужного поля, перейдите к ответу Mark Byers. Я просто хотел показать другой способ сделать то, что вы хотите: просто используйте лямбду для выбора поля, как вы делаете во многих других методах Linq:

protected int GetHourRateDB(string serviceType, 
                            Func<CalculatorData, int> fieldSelector)
{
    using(CalculatorLinqDataContext context = new CalculatorLinqDataContext())
    {
        return fieldSelector(
                  (from calculatorData in context.CalculatorDatas
                   where calculatorData.Service == serviceType
                   select calculatorData).Single()
               );
    }
}

Вы бы использовали это как:

int someSmallValue = GetHourRateDB("Writing", x => x.Small);
int someMediumValue = GetHourRateDB("Writing", x => x.Medium);

Имейте в виду, что Single() выдает InvalidOperationException, если в базе данных нет элемента с указанным типом serviceType. Вы должны как-то справиться с этим.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...