I have following method in my Project.
public IEnumerable<T> GetAll()
{
return _context.Set<T>().ToList();
}
Then my DbContext has this..
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Entity<Product>.ToTable("Product");
}
This works fine, as long as "Product" Model is within same project.
However, different clients will be consuming my DataAccess layer and they will be passing Models of different types. How can I tell EntityFramework to dynamically Bind a Model to a "Table" in SQL server.
I was able to resolve this problem by doing the following.
public class Repository<T> : DbContext, IRepository<T> where T : BaseModel
{
public DbContext _context { get; set; }
public DbSet<T> _dbSet { get; set; }
public Repository(string con)
: base(con)
{
}
public IEnumerable<T> GetAll()
{
return _dbSet;
}
public void Add(T entity)
{
_dbSet.Add(entity);
_context.SaveChanges();
}
}
Basicly the steps are...
A. Class must inherit DbContext.
A Generic Property for DbSet.
Now DbSet is a Generic Table, which you can use in your Generic Repoitory.
Related
I am currently working on a codebase, to which I want to add a number of new entities with corresponding owned entities. Because, in some other part of the codebase I won't touch, UseLazyLoadingProxies is called; I receive the following exception:
System.InvalidOperationException : Navigation property 'Foo' on entity type 'FooOwner' is not virtual. UseLazyLoadingProxies requires all entity types to be public, unsealed, have virtual navigation properties, and have a public or protected constructor.
If I mark the property as virtual, the owned entity goes into a new table; which I do not want either.
According to github issues I encountered, these seem to be the expected behavior.
My question is this: Is there a way to work around this problem, such that, I can somehow mark the owned entity to be stored in the same table as the owner entity, and if possible to be always Included, eagerly loaded.
using System.Diagnostics;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using NUnit.Framework;
namespace StackOverflowObjectContext.Tests
{
public class Foo
{
public long Id { get; set; }
public int Data { get; set; }
}
public class FooOwner
{
public int Id { get; set; }
public Foo Foo { get; set; }
}
public class FooOwnerMap : IEntityTypeConfiguration<FooOwner>
{
public void Configure(EntityTypeBuilder<FooOwner> builder)
{
builder.HasKey(x => x.Id);
builder.HasOne(x => x.Foo);
}
}
public class StackOverflowObjectContext : DbContext
{
public StackOverflowObjectContext(DbContextOptions options) : base(options) { }
DbSet<FooOwner> FooOwners { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new FooOwnerMap());
base.OnModelCreating(modelBuilder);
}
}
[TestFixture]
public class StackOverflowTest
{
StackOverflowObjectContext _objectContext;
[SetUp]
public void SetUp()
{
var builder = new DbContextOptionsBuilder<StackOverflowObjectContext>()
.UseSqlServer(#"Data Source=.\SQLEXPRESS;Initial Catalog=StackOverflow;Integrated Security=True")
.UseLazyLoadingProxies();
_objectContext = new StackOverflowObjectContext(builder.Options);
}
[Test]
public void CanGenerateCreateScript()
{
var script = _objectContext.Database.GenerateCreateScript();
Debug.WriteLine(script);
}
}
}
You should use OwnsOne instead of HasOne
The entity type 'MyType' cannot be added to the model because a query type with the same name already exists.
public class MyContext : DbContext
{
public DbQuery<MyType> MyTypes { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//Exception is thrown here
//needed b/c table is not named MyTypes
modelBuilder.Entity<MyType>()
.ToTable("MyType");
}
}
Change DbQuery to DbSet. Keyless Entity Types are used for Views, among other things.
public class MyContext : DbContext
{
//DbSet not DbQuery
public DbSet<MyType> MyTypes { get; set; }
}
Apparently you and I had the same problem on the same day :)
My issue was that I had my view set up as DBset:
public virtual DbSet<VwVendors> VwVendors{ get; set; }
But my mapping was set up as follows:
modelBuilder.Query<VwVendors>()
.ToView("vw_Vendors");
My fix was to do the opposite of what you did. I had to change DbSet to DbQuery.
Your answer helped me get mine :D
I am creating a MVC application using EF 6.0.0.0 and ODP.Net Oracle.ManagedDataAccess version 4.121.2.0 for the data access.
And when I load the Locations/Create.cshtml page I got the following Exception:
ORA-00942: table or view does not exist
While I have used the link below
Table Does Not Exist while using EF 6 and Oracle.ManagedDataAccess
Here is how my Context :
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext()
: base("QAContextConnectionString")
{
Database.SetInitializer<ApplicationDbContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("AMICOS");
base.OnModelCreating(modelBuilder);
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
public DbSet<Location> Locations { get; set; }
}
I have an autogenerated dbcontext from EF. I've created a partial class of this autogenerated EF class so I can make it implement an interface so that I can pass that interface to my service that will use it. That'll get passed in via Unity.MVC DI framework. When I try to register this interface to the actual class I'm getting an error:
"There is no implicit reference conversion from ContactsEntities to IContactsEntities."
I'm not sure why I'm getting that or how to solve it.
EF Autogen file:
public partial class ContactsEntities : DbContext
{
public ContactsEntities()
: base("name=ContactsEntities")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<Contact> Contacts { get; set; }
}
My file:
public interface IContactsEntities
{
DbSet<Contact> Contacts { get; set; }
}
public partial class ContactsEntities : IContactsEntities
{
public virtual DbSet<Contact> Contacts { get; set; }
}
Unity registering that gives the error:
container.RegisterType<IContactsEntities, ContactsEntities>();
I am facing a scenario in which I need to prevent direct creation of entity objects.
I am using Code First. I would like to have a method somewhere only using which I should be able to create the object. Is there any commonly used practice for this?
EF can work with entities having private/protected constructors.
So lets take this sample context:
public class MyEntity
{
protected MyEntity() { }
public int Id { get; set; }
public string Name { get; set; }
}
public class MyContext : DbContext
{
public DbSet<MyEntity> MyEntities { get; set; }
}
Then creating an entity with new MyEntity() will result in compilation error.
But you can still create entites through EF with DbSet.Create myContext.MyEntities.Create(); and all other operations on MyEntity will work e.g. queries and updates etc as expected.
And of course you can also have a static factory method on MyEntity which manages the object creation
public class MyEntity
{
//...
public static MyEntity MyCreate()
{
return new MyEntity();
}
}