У меня есть некоторые типы, которые расширяют общий тип, и это мои модели.
Затем у меня есть типы DAO для каждого типа модели для операций CRUD.
Теперь мне нужна функция, которая позволит мне найти идентификатор, заданный для любого типа модели, поэтому я создал новый тип для некоторых разных функций.
Проблема в том, что я не знаю, как заказать эти типы. В настоящее время у меня есть модели до dao, но мне как-то нужно DAOMisc
до CityDAO
и CityDAO
до DAOMisc
, что невозможно.
Простым подходом было бы поместить эту функцию в каждый DAO, ссылаясь только на типы, которые могут возникнуть перед ним, поэтому State
предшествует City
, поскольку State
имеет отношение внешнего ключа с City
, поэтому разная функция будет очень короткой. Но это просто поражает меня как неправильное, поэтому я не уверен, как наилучшим образом подойти к этому.
Вот мой разный тип, где BaseType
- общий тип для всех моих моделей.
type DAOMisc =
member internal self.FindIdByType item =
match(item:BaseType) with
| :? StateType as i ->
let a = (StateDAO()).Retrieve i
a.Head.Id
| :? CityType as i ->
let a = (CityDAO()).Retrieve i
a.Head.Id
| _ -> -1
Вот один тип dao. CommonDAO
на самом деле имеет код для операций CRUD, но здесь это не важно.
type CityDAO() =
inherit CommonDAO<CityType>("city", ["name"; "state_id"],
(fun(reader) ->
[
while reader.Read() do
let s = new CityType()
s.Id <- reader.GetInt32 0
s.Name <- reader.GetString 1
s.StateName <- reader.GetString 3
]), list.Empty
)
Это мой тип модели:
type CityType() =
inherit BaseType()
let mutable name = ""
let mutable stateName = ""
member this.Name with get() = name and set restnameval=name <- restnameval
member this.StateName with get() = stateName and set stateidval=stateName <- stateidval
override this.ToSqlValuesList = [this.Name;]
override this.ToFKValuesList = [StateType(Name=this.StateName);]
Цель этой функции FindIdByType
заключается в том, что я хочу найти идентификатор для отношения внешнего ключа, поэтому я могу установить значение в моей модели, а затем, чтобы функции CRUD выполняли операции со всей правильной информацией. Таким образом, City
требуется идентификатор для имени состояния, поэтому я бы получил имя состояния, поместил его в тип State
, а затем вызовет эту функцию, чтобы получить идентификатор для этого состояния, поэтому моя вставка города также будет включать id для внешнего ключа.
Это, по-видимому, лучший подход, очень общий способ обработки вставок, который является текущей проблемой, которую я пытаюсь решить.
UPDATE:
Мне нужно исследовать и посмотреть, смогу ли я каким-то образом ввести метод FindIdByType в CommonDAO после того, как будут определены другие DAO, почти как бы закрытие. Если бы это была Java, я бы использовал AOP для получения функциональности, которую я ищу, но не уверен, как это сделать в F #.
Окончательное обновление:
Подумав о моем подходе, я понял, что это было смертельно ошибочно, поэтому я придумал другой подход.
Вот как я буду делать вставку, и я решил включить эту идею в каждый класс сущностей, что, вероятно, является лучшей идеей.
member self.Insert(user:CityType) =
let fk1 = [(StateDAO().Retrieve ((user.ToFKValuesList.Head :?> StateType), list.Empty)).Head.Id]
self.Insert (user, fk1)
Я еще не начал использовать fklist
, но это int list
, и я знаю, какое имя столбца относится к каждому из них, поэтому мне просто нужно сделать inner join
для выбора, например.
Это базовая вставка типа, которая обобщается:
member self.Insert(user:'a, fklist) =
self.ExecNonQuery (self.BuildUserInsertQuery user)
Было бы неплохо, если бы F # мог делать co/contra-variance, поэтому мне пришлось преодолеть это ограничение.