Wymagana referencja

0

Witam,
tworze sobie teraz mały projekt oparty o ASP.NET MVC 5, chciałem w nim całą logikę związaną z bazą danych przenieść do DLL włącznie z Entity Framework. Po usunięciu EF z projektu MVC dodałem go do DLL, lecz teraz gdy klasę z DLL która dziedziczy po DbContext chce utworzyć w projekcie MVC dostaję błąd kompilacji.

The type 'System.Data.Entity.DbContext' is defined in an assembly that is not referenced.

Rozwiązaniem jest ponowne dodanie do projektu MVC Entity Framework. Co jest przyczyną tego problemu?

0

wydaje mi się że w tej DLL'ce używasz bibliotek których do niej potem nie dołączasz.

0

Dołączam na pewno bo testowo w DLL tworze ten sam obiekt bez problemu. W załączniku dodałem projekt który przedstawia problem.

2

Bo Twoja klasa EFContext dziedziczy po DbContext. Dlatego musisz mieć w projekcie EFTest też wiedzieć, czym jest sam DbContext.

http://stackoverflow.com/questions/11608008/inheritence-in-c-sharp-and-referencing-a-dll-containing-the-base-class

Źle to projektujesz, projekt z MVC nie powinien bezpośrednio korzystać na DbContext (ani niczym, co po tym dziedziczy), a z osobnej warstwy serwisowej, która udostępnia konkretne biznesowe metody.

0

Tak się zastanawiałem czy nie pozbyć się całkowicie EF w projekcie MVC, i teraz na pewno go wywalę. Dzięki za linka.
Rozumiem że do pamięci zostanie załadowana tylko 1 DLL?

0

Tak jak napisałeś wywaliłem cały EF z projektu, wszystko mi już działa tak jak chciałem. Teraz jedynie został mi dylemat czy wywalić z DLL zawierającej logikę biznesową referencje do Microsoft.AspNet.Identity.Core.dll. Dylemat wynika z tego że jeżeli ją usunę to nie będę miał dostępu do interfejsów IRole i IUser, przez co muszę umożliwić tworzenie generycznego kontekstu.

public class BizBoxDbContext<TUser, TRole> : DbContext
    where TUser : User
    where TRole : Role
{
    public BizBoxDbContext()
        : base("BizBoxDbContext")
    { }

    public DbSet<TUser> Users { get; set; }
    public DbSet<TRole> Roles { get; set; }
    internal DbSet<Claim> Claims { get; set; }
}

Generyczny kontekst możliwa w projekcie MVC utworzenie klasy użytkownika która dziedziczy po User oraz IUser, lecz przez to nie tylko kontekst musi być generyczny ale także wszystkie serwisy oparte o ten kontekst.
Jak myślisz które rozwiązanie jest lepsze, generyczny kontekst i serwisy czy odniesie się do Microsoft.AspNet.Identity.Core.dll w DLL domeny?

0

Domena nie powinna zależeć od infrastruktury.

0

Staram się do tej zasady stosować, tylko czy czasem aby to nie jest zbyt kręta droga? Na przykład jak w moim przypadku gdzie chcą trzymać się tej zasady zmuszony będę tworzyć wszystkie serwisy jako generyczne i to z dwoma parametrami. Czy może jednak nie jest to taka wielka komplikacja jak mi się wydaje, w porównaniu do tego co dam nam całkowicie niezależna domena?

0

@Bumcykowy, no cóż, programowanie jest jak życie - to sztuka wyboru i kompromisów.
Jeśli uważasz, że ścisłe trzymanie się jakichś zasad daje Ci tylko sporo roboty bez żadnych zysków, to się ich nie trzymaj, tylko pamiętaj, że kiedyś może się okazać, że popełniłeś błąd.

I nie rozumiem, o co chodzi z tymi serwisami z dwoma parametrami generycznymi, mógłbyś dokładniej wyjaśnić?

0

Chcąc użyć ASP.NET Identity musimy mieć klasy dziedziczące IUser oraz IRole które są właśnie dostarczone przez niego samego, ale jeżeli pozbawimy bibliotekę zawierającą domenę odniesienia do ASP.NET Identity to w projekcie MVC będzie trzeba odziedziczyć po klasie User z domeny oraz IUser z ASP.NET Identity.

public class AppUser : User, IUser
    {
        string IUser<string>.Id
        {
            get { return UserId.ToString(); }
        }

        public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<AppUser> manager)
        {
            var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie);
            return userIdentity;
        }
    }

I teraz aby tą nowo utworzoną klasę móc odwzorować w bazie danych musimy mieć generyczny kontekst Entity Framework, bo samo rzutowanie nie wystarczy z klasy AppUser na User(dostaniemy wyjątek o brakujących meta danych).
Następnie jeżeli będziemy tworzyć serwisy oparte o ten generyczny kontekst to one także będą musiały być generyczne, w najlepszym przypadku dwuparametrowe a może i więcej.

public interface IUserService<TUser, TRole> : IDisposable
{
    #region TUser
    Task CreateAsync(TUser TUser);
    Task DeleteAsync(TUser TUser);
    Task<TUser> FindByIdAsync(Guid TUserId);
    Task<TUser> FindUserByNameAsync(string TUserName);
    Task UpdateAsync(TUser TUser);
    #endregion
}
public class UserService<TUser, TRole> : IUserService<TUser, TRole>
    where TUser : User
    where TRole : Role
{
    private BizBoxDbContext<TUser, TRole> db;

    public UserService()
    {
        db = new BizBoxDbContext<TUser, TRole>();
    }

    public static IUserService<TUser, TRole> Create()
    {
        return new UserService<TUser, TRole>();
    }

    public void Dispose()
    {
        db.Dispose();
    }

    #region User
    public async Task CreateAsync(TUser user)
    {
        user.UserId = Guid.NewGuid();
        db.Users.Add(user);
        await db.SaveChangesAsync();
    }

    public async Task DeleteAsync(TUser user)
    {
        db.Users.Remove(user);
        await db.SaveChangesAsync();
    }

    public async Task<TUser> FindByIdAsync(Guid userId)
    {
        return await db.Users.FindAsync(userId);
    }

    public async Task<TUser> FindUserByNameAsync(string userName)
    {
        return await db.Users.SingleOrDefaultAsync(u => u.UserName == userName);
    }

    public async Task UpdateAsync(TUser user)
    {
        db.Entry(user).State = EntityState.Modified;
        await db.SaveChangesAsync();
    }
    #endregion
}
0

Pomysl [nie testowane]
Zrob tak:
Data -> AppUser : User (czy cos tam)
DataAccess -> DbContext : TenIchSmiesznyContext
Business -> Repozytoria
Web -> Kontrolery

Wady:
Bedziesz musial miec referencje do do roznych dziwnych rzeczy, w miejscach, w ktorych nie powinna ona wystapic.

Zalety:
Nie masz tyle nawiasow trojkatnych na cm kwadratowy IDE.

Lepszy pomysl:
Olac ASP.NET Identity.

0

@n0name_l
Nie za bardzo rozumiem ten schemat który opisałeś jak byś mógł więcej szczegółów podać. Dodatkowo nie chciał bym rezygnować z ASP.NET Identity a konkretnie z Core.

@somekind
Co twoim zdaniem będzie lepsze, odniesienie do DLL czy generyczne serwisy?

1 użytkowników online, w tym zalogowanych: 0, gości: 1