Я пытался выяснить сценарий, в котором такой подход мог бы быть полезен, не приводя к раздутому кешу, который безумно сложно поддерживать.
Я знаю, что это не дает прямого ответа на ваш вопрос, но я хочу задать несколько вопросов об этом подходе, который на первый взгляд может показаться заманчивым:
- Как вы планировали управлять упорядочением параметров? То есть. (x => x.blah == "slug" &&! x.Deleted) ключ кэша должен равняться (x =>! x.Deleted && x.blah == "slug") ключ кэша.
- Как вы планировали избегать дублирования объектов в кеше? То есть. Одна и та же ферма из нескольких запросов по своему дизайну будет кэшироваться отдельно с каждым запросом. Скажем, для каждого слага, который появляется в ферме, у нас есть отдельная копия фермы.
- Расширение вышеперечисленного с помощью большего количества параметров, таких как участок, фермер и т. Д., Приведет к большему количеству совпадающих запросов, каждый из которых будет иметь отдельную копию кэшированной фермы. То же самое относится к каждому типу, который вы можете запросить, плюс параметры могут быть не в том же порядке
- Теперь, что произойдет, если вы обновите ферму? Не зная, какие кэшированные запросы будут содержать вашу ферму, вы будете вынуждены уничтожить весь кеш. Какой вид противодействует тому, чего вы пытаетесь достичь.
Я вижу причины такого подхода. Уровень производительности 0-обслуживания. Однако, если вышеперечисленные пункты не приняты во внимание, подход сначала убьет производительность, затем приведет к множеству попыток сохранить ее, а затем окажется совершенно несостоятельным.
Я был на этом пути. В конце концов потратил много времени и сдался.
Я нашел гораздо лучший подход, кэшируя каждую результирующую сущность отдельно, когда результаты поступают из бэкэнда с методом расширения для каждого типа отдельно или через общий интерфейс.
Затем вы можете создать метод расширения для ваших лямбда-выражений, чтобы сначала попробовать кеш, прежде чем нажимать на db.
var query = (x => x.Crops.Any(y => slug == y.Slug) && x.Deleted == false);
var results = query.FromCache();
if (!results.Any()) {
results = query.FromDatabase();
results.ForEach(x = x.ToCache());
}
Конечно, вам все равно нужно будет отслеживать, какие запросы действительно попали в базу данных, чтобы избежать запроса A, возвращающего 3 фермы из БД, удовлетворяющих запросу B, с одной совпадающей фермой из кэша, в то время как в базе данных фактически будет доступно 20 совпадающих ферм. Таким образом, каждый запрос stll должен попадать в БД хотя бы один раз.
И вам нужно отслеживать запросы, возвращающие 0 результатов, чтобы избежать их, следовательно, бесполезного попадания в БД.
Но в целом вы получаете намного меньше кода и в качестве бонуса, когда вы обновляете ферму, вы можете
var farm = (f => f.farmId == farmId).FromCache().First();
farm.Name = "My Test Farm";
var updatedFarm = farm.ToDatabase();
updatedFarm.ToCache();