• Как найти одинаковые вхождения в словаре?

    @dmitryKovalskiy
    программист средней руки
    Если через LINQ то кажется так
    arr1.Where(d => arr2.Contains(d));
    Ответ написан
    Комментировать
  • Как предотвратить кэширование отдельных ссылок?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Запросы изменяющие состояние должны отправляться методом POST.
    Ответ написан
    1 комментарий
  • Как реализовать маршрутизацию в виде domain.com/users и domain.com/user/123?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    routes.MapRoute(
        "UsersGeneric",
        "{action}/{id}",
        new { 
          controller = "Users",
          action = "User",
          id = UrlParameter.Optional
        },
        new[] { controller = "Users", id=@"\d+" },
        new[] { "Proj.Controllers" }
    );
    
    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new { 
            controller = "Home", 
            action = "Index", 
            id = UrlParameter.Optional 
        },
        new[] { "Proj.Controllers" }
    );
    Ответ написан
    2 комментария
  • Что не так с ASP.NET Identity в Onion архитектуре?

    Valeriy1991
    @Valeriy1991
    Разработчик .NET C# (ASP.NET MVC) в Alfa-B, Moscow
    Добрый день!

    Правильно ли я реализовал Repository + UnitOfWork

    Ну, насколько я знаю, существует множество реализаций UnitOfWork + Repository, и каждая их них обладает своими достоинствами и недостатками. У Вас все выглядит достаточно работоспособно и юнит-тестируемо.

    Правильно ли реализовано Dispose

    В принципе, да. Только вот private fields на то и private, чтобы их инкапсулировать. Считаю очень неправильным, что у вас переменная disposed имеет модификатор public. Еще видел где-то в сети, что рекомендуют явно присваивать в переменную db значение null после вызова db.Dispose():
    if (_db != null)
    {
        _db.Dispose();
        _db = null;
    }

    Не хочу показаться навязчивым или развивать тему холивара, но именовать private field через символ "_" в начале имени, на мой взгляд, все же удобнее. Т.е. вместо private DbContext db лучше написать private DbContext _db. Как мне кажется, визуально такой код другим людям читать легче.

    В каком слое по вашему должен находится ApplicationSignInManager, ведь он использует OWIN и работает с ApplicationUserManager

    Зависит от сложности Вашего приложения. Может быть такая ситуация, что MVC-приложений несколько, но они должны использовать один механизм авторизации/аутентификации. Тогда компонент ApplicationSignInManager можно вынести в отдельный проект. Если такой необходимости нет, то, на мой взгляд, можно спокойно оставить его в клиенте (MVC-app).

    Ввиду того что о базе и орм не знает ни один слой кроме DAL я решил вынести connectionString в константу, это нормальный подход?

    Нет. Строки подключения к БД лучше всего хранить как настроечные параметры. Для ASP.NET 5 - в web.config, например. Для ASP.NET Core - например, в файле appsettings.json.

    Есть смысл вынести сущности в отдельный проект и отделить их от аннотаций для бд?

    Однозначно. Потому что Ваши сущности представляют доменную модель. Выделение их в отдельный проект позволит сделать более модульной Вашу архитектуру, а следовательно, Вы сможете подрубать этот проект только там, где он нужен, не таща с собой всякие DbContext-ы, Repository, UnitOfWork-и и др.


    В примере в owin контекст засовывают ef контекст вот таким образом app.CreatePerOwinContext(ApplicationDbContext.Create); насколько это оправдано и стоит ли так делать?
    В реализации UserStore для EF очень странно ведут себя с dispose и у меня ощущения что некоторые данные висят в памяти постоянно, так ли это?

    Вот тут не подскажу. Буду рад также услышать компетентное мнение.

    Насколько вообще оправдан такой велосипед?

    Какой именно велосипед? :) Если собственная реализация всяких ***Store, то думаю, да, потому что иначе их развязать и расположить в разных слоях не получится (сам мучился этим вопросом, и в итоге, потратив тонну времени, последовал совету делать свои реализации ***Store, чтобы делать архитектуру более модульной и упрощающей юнит-тестирование).

    В свое время мне очень помогла вот эта серия статей (из 4 частей): techbrij.com/generic-repository-unit-of-work-entit...
    Ответ написан
    1 комментарий
  • Lua vs C# для разработки игр и иные задачи? Что лучше и перспективнее учить?

    abyrkov
    @abyrkov
    JavaScripter
    Это некорректные сравнения.
    Lua - это скриптовый язык со всеми вытекающими
    C# - это "полнофункциональный" ЯП, т.е. заведомо мощнее и сложнее.

    Перспективнее - C#, но это, разумеется, ИМХО
    Ответ написан
    1 комментарий
  • Я не умею готовить репозиторий или он просто не очень?

    Valeriy1991
    @Valeriy1991
    Разработчик .NET C# (ASP.NET MVC) в Alfa-B, Moscow
    Коллеги, добрый день!

    Почему никто не упомянул про паттерн UnitOfWork? Паттерн репозиторий становится очень удобным в использовании, если:
    1. это паттерн GenericRepository;
    2. при необходимости можно добавить конкретные репозитории (я их называю ConcreteRepository;
    3. ну и конечно же, если всем этим управляет UnitOfWork;


    При использовании такой связки у Вас:
    • если много сущностей и есть GenericRepository, то вам не нужно плодить репозиторий на каждую сущность - достаточно сделать так: var unit = UnitOfWork.Repository<UserLog>();
    • пункт выше автоматически решает проблему "как выбрать данные из 2-3-4-... таблиц" - с репозиториями вы работаете как с DbSet в EF (кстати, сам DbContext из EF, по сути, реализует паттерн UnitOfWork и GenericRepository);
    • автоматически решается вопрос расширения вашего репозитория методами на каждый чих (т.е. надо получить список логов для конкретного пользователя - добавляем новый метод GetLogsByUserId в репозиторий) - не нужно накручивать репозиторий новыми методами, достаточно сделать так: var unit = UnitOfWork.Repository<UserLog>().GetQuery(e => e.UserId == targetUserId) или var unit = UnitOfWork.Repository<UserLog>().AsQuaryableQuery(e => e.UserId == targetUserId) (методы GetQuery и AsQuaryableQuery - это методы у сущности UnitOfWork, которые возвращают IEnumerable или IQueryable соответственно);
    • если методы SaveChanges/Commit реализованы в UnitOfWork (и UnitOfWork управляет транзакциями БД), то у вас решается проблема консистентности данных - UnitOfWork либо подтверждает все изменения (Commit), либо откатывает в случае ошибок (Rollback);
    Или мне спецальный класс завести в которомом сразу будут все репозитории(как dbContext прям)?

    Правильно мыслите - этот специальный класс и есть UnitOfWork. Он "прям как dbContext", только таким образом вы абстрагируетесь от всяких EF, NHibernate и прочих ORM. В итоге вашей бизнес-логике по барабану, какую ORM вы используете.

    Если мне нужен в 1 контроллере/сервисе не 1 репозиторий? мне по 1 их подключать? может мне 15 надо.

    Достаточно подключить 1 UnitOfWork (и лучше это делать через внедрение зависимостей - DI - DependencyInjection с использованием IoC-контейнера, например, Autofac, Ninject, Unity. Autofac лично мне нравится больше хотя бы потому, что у него самая адекватная и понятная документация, чем у Ninject и уж тем более Unity [нет, это не тема для холивара "кто лучше: Autofac/Ninject/Unity/... - это всё выводы из моего личного опыта]).

    И главный вопрос. Нужно ли вообще применять этот паттерн если ты не используешь юнит тестирование, либо не используешь его для покрытия 100% всего кода а только отдельные хелперы? Ведь для перехода на другую бд достаточно будет сменить провайдер если используешь ef, и если вы используете орм врядли вы полностью от неё откажетесь. Зачем писать кучу кода "наперед" с принципом "а вот вдруг мы поменяем бд/ос", да это скорей всего уменьшит изменения кода по сравнению с полной переписыванием проекта. Но если ты уверен что ос и бд не поменяется?

    В любом enterprise-проекте надо думать наперед, даже если это проект "маленький интернет-магазинчик". Потому что через год этот маленький интернет-магазинчик может превратиться в нормальный такой бизнес с очень высокими оборотами и прибылью, и тогда, если у Вас не будет хорошей абстрагированной архитектуры, если у вас не будет модульности, то любая новая задача будет реализовываться со все большим количеством костылей, и любая новая задача будет приводить к неустойчивости системы и повышению степени регресса (проверено!). А вот если вы как архитектор вложите при разработке в вашу систему модульность и абстрагирование компонентов, то вы тем самым уже упростите себе жизнь в будущем, а это означает, что через какое-то время любая задача по изменению системы будет решаться быстрее, надежнее, а значит, вы сможете брать как разработчик за это больше денег (потому что стоимость новых изменений будет гораздо ниже). А если вы еще и юнит-тестирование будете использовать при разработке, то тем самым вы снижаете риск регресса в поведении вашей системы, что опять же, снижает стоимость разработки лично для вас. Поверьте, когда система имеет хотя бы модульность и абстрагирование компонентов друг от друга (т.е. какой-либо компонент зависит от абстракции - в виде интерфейса или абстрактного класса, а не от реализации - в виде конкретного класса), то работа с такой системой будет доставлять удовольствие.

    СУБД менять - это не такая распространенная практика, а вот от ORM (и от EF в частности) отказываться в пользу производительности - это реальный кейс с ростом нагрузки.

    Толстый Лорри - абсолютно с Вами согласен по этому поводу.

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

    Михаил еще также указал в комментарии, в каких случаях репозиторий можно не использовать. Добавлю: в не-enterprise-решениях. Например, вы делаете какой-нибудь простенький сайт для себя. Или для друга. Или просто для изучения новой технологии.
    Ответ написан
    8 комментариев
  • Я не умею готовить репозиторий или он просто не очень?

    @Free_ze
    Пишу комментарии в комментарии, а не в ответы
    Желательно почитать по поводу работы EF и IQuerable в частности. С помощью этого интерфейса и LINQ вы сможете формировать запросы (которые рендерятся в нативный SQL), а не просто фильтровать коллекции.
    private IQuerable<Student> GetLogs()
    {
        return context.Logs;
    }   
    public IEnumerable<Student> GetLogsForStudent(int id, DateTime from, DateTime to)
    {
        return GetLogs().Where(x => x.Id == id
                                    && x.Date >= from
                                    && x.Date <= to)
                        .ToList();
    }


    Все используют lazy loading?

    Зависит от количества данных и критичности по скорости.

    Если мне нужен в 1 контроллере/сервисе не 1 репозиторий? мне по 1 их подключать?

    Да, по одному. А можно в сервис или UnitOfWork объединять.

    Изачем он для юнит тестов если можно спокойно moqнуть весь dbcontext?

    dbcontext мокать нет смысла хотя бы потому, что он гвоздями к EF прибит. СУБД менять - это не такая распространенная практика, а вот от ORM (и от EF в частности) отказываться в пользу производительности - это реальный кейс с ростом нагрузки.
    Ответ написан
    Комментировать
  • Как создать св-во, которое не нужно хранить в БД при model first подходе?

    yarosroman
    @yarosroman Куратор тега C#
    C# the best
    создайте отдельный файл
    public partial class Book{
            [NotMapped]
            public int AvailableCount {
                        get
                        {
                            // Логика..
                            int someInt = 12;
                            return someInt;
                        }
                    }
    }

    и не перезатрется у вас ничего

    ну или в MS SQL есть вычисляемые поля, думаю их будет вернее использовать.
    Ответ написан
    Комментировать