EF Core + MVC 6 + .NET Core RC2 - EF not returning results - asp.net-mvc

Entity Framework Core is not returning any results. I've been searching near and far. I find some tutorials saying one thing and others saying another. Here is what I have so far:
Buyer.cs
[Table("DealerCustomer", Schema = "dbo")]
public class Buyer
{
[Key]
public int DealerCustomerKey { get; set; }
public int DealerId { get; set; }
}
BuyerContext.cs
public class BuyerContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer("db connection string here");
}
public DbSet<Buyer> Buyers { get; set; }
}
Startup.cs > ConfigureServices function
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddApplicationInsightsTelemetry(Configuration);
services.AddDbContext<BuyerContext>(options =>
options.UseSqlServer("db connection string here");
services.AddMvc();
}
Now I am trying to load the Buyers data from my BuyerController.cs:
[Route("api/[controller]")]
public class BuyersController : Controller
{
private BuyerContext _context;
public BuyersController(BuyerContext context)
{
_context = context;
}
[HttpGet]
public IEnumerable<Buyer> Get()
{
System.Diagnostics.Debug.WriteLine("getting buyers");
System.Diagnostics.Debug.WriteLine(_context.Buyers);
return _context.Buyers;
}
}
This is all returning empty brackets when I load the page, instead of a list of Buyers. However there are over 1000 rows in that table (dbo.DealerCustomer). I know I have two places adding the db connection string but tutorials kept show both ways of doing it and when I only did it in startup.cs I was getting errors about the _context. I can make everything look pretty later, right now I just want a good connection so I have a starting place to work from.

I found there was a timeout because one of the decimal fields was returning null.
EF Core Timing out on null response

Related

ASP MVC EF6 Architecture

We have ASP MVC web project. After reading a lot of articles and discussions here in stackoverflow about the correct architechture we have decided to go with the following one, although there is not only one correct way of doing things this is the way we have decided, but we still have some doubts.
We are publishing this here not only to be helped but also to show what we have done in case it is helpful to somebody.
We are working in ASP .NET MVC project, EF6 Code first with MS SQL Server.
We have divided the project into 3 main layers that we have separate into 3 projects: model, service and web.
The model creates the entities and setup the DataContext for the database.
The service make the queries to the data base and transform those entities into DTOs to pass them to the web layer, so the web layer doesn't know anything about the database.
The web uses AutoFac for the DI (dependency Injection) to call the services we have in the service layer and obtain the DTOs to transform those DTOs into Model Views to use them in the Views.
After reading a lot of articles we decided not to implement a repository pattern and unit of work because, in summary, we have read the EF acts as a unit of work itself. So we are simplifying things a little here.
https://cockneycoder.wordpress.com/2013/04/07/why-entity-framework-renders-the-repository-pattern-obsolete/
This is the summary of our project. Now I'm going to go through every project to show the code. We are going to show only a couple of entities, but our project has more than 100 different entities.
MODEL
Data Context
public interface IMyContext
{
IDbSet<Language> Links { get; set; }
IDbSet<Resources> News { get; set; }
...
DbSet<TEntity> Set<TEntity>() where TEntity : class;
DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
}
public class MyDataContext : DbContext, IMyContext
{
public MyDataContext() : base("connectionStringName")
{
}
public IDbSet<Language> Links { get; set; }
public IDbSet<Resources> News { get; set; }
...
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Properties<DateTime>().Configure(c => c.HasColumnType("datetime2"));
}
}
Here is how we declare the entities
public class Link
{
public int Id{ get; set; }
public string Title { get; set; }
public string Url { get; set; }
public bool Active { get; set; }
}
SERVICES
These are the generic classes we use for all the services.
As you see we use the DTOs to get data from the web layer. Also we connect to the database using Dbset = Context.Set()
public interface IService
{
}
public interface IEntityService<TDto> : IService where TDto : class
{
IEnumerable<TDto> GetAll();
void Create(TDto entity);
void Update(TDto entity);
void Delete(TDto entity);
void Add(TDto entity);
void Entry(TDto existingEntity, object updatedEntity);
void Save();
}
public abstract class EntityService<T, TDto> : IEntityService<TDto> where T : class where TDto : class
{
protected IClientContext Context;
protected IDbSet<T> Dbset;
protected EntityService(IClientContext context) { Context = context; Dbset = Context.Set<T>(); }
public virtual IEnumerable<TDto> GetAll()
{
return Mapper.Map<IEnumerable<TDto>>(Dbset.AsEnumerable());
}
public virtual void Create(TDto entity)
{
if (entity == null)
{
throw new ArgumentNullException(nameof(entity));
}
Dbset.Add(Mapper.Map<T>(entity));
Context.SaveChanges();
}
public virtual void Update(TDto entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
Context.Entry(entity).State = EntityState.Modified;
Context.SaveChanges();
}
public virtual void Delete(TDto entity)
{
if (entity == null) throw new ArgumentNullException(nameof(entity));
Dbset.Remove(Mapper.Map<T>(entity));
Context.SaveChanges();
}
public virtual void Add(TDto entity)
{
Dbset.Add(Mapper.Map<T>(entity));
}
public virtual void Entry(TDto existingEntity, object updatedEntity)
{
Context.Entry(existingEntity).CurrentValues.SetValues(updatedEntity);
}
public virtual void Save()
{
Context.SaveChanges();
}
}
We declare the DTOs in this project (this is a very simple example so we don't have to put all the code here):
public class LinkDto
{
public int Id { get; set; }
public string Title { get; set; }
public string Url { get; set; }
public bool Active { get; set; }
}
Then one of our services:
public interface ILinkService : IEntityService<LinkDto>
{
IPagedList<LinkDto> GetAllLinks(string searchTitle = "", bool searchActive = false, int pageNumber = 1, int pageSize = 10);
LinkDto FindById(int id);
LinkDto Test();
}
public class LinkService : EntityService<Link, LinkDto>, ILinkService
{
public LinkService(IClientContext context) : base(context) { Dbset = context.Set<Link>(); }
public virtual IPagedList<LinkDto> GetAllLinks(bool searchActive = false, int pageNumber = 1, int pageSize = 10)
{
var links = Dbset.Where(p => p.Active).ToPagedList(pageNumber, pageSize);
return links.ToMappedPagedList<Link, LinkDto>();
}
public virtual LinkDto FindById(int id)
{
var link = Dbset.FirstOrDefault(p => p.Id == id);
return Mapper.Map<LinkDto>(link);
}
public LinkDto Test()
{
var list = (from l in Context.Links
from o in Context.Other.Where(p => p.LinkId == l.Id)
select new OtherDto
{ l.Id, l.Title, l.Url, o.Other1... }).ToList();
return list;
}
}
As you see we use AutoMapper (version 5 which has changed a little) to transform from Entities to DTOs the data.
One of the doubts we have is if the use of "Dbset.Find" or "Dbset.FirstOrDefault" is correct and also if the use of "Context.Links" (for any entity).
WEB
FInally the web project where we receive the DTOs and transform those DTOs into ModelViews to show in our views.
We need to call, in the Global.asax Application_Start, AutoFac to do the DI so we can use our services.
protected void Application_Start()
{
...
Dependencies.RegisterDependencies();
AutoMapperBootstrapper.Configuration();
...
}
public class Dependencies
{
public static void RegisterDependencies()
{
var builder = new ContainerBuilder();
builder.RegisterControllers(typeof(MvcApplication).Assembly).PropertiesAutowired();
builder.RegisterModule(new ServiceModule());
builder.RegisterModule(new EfModule());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
}
}
public class ServiceModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(Assembly.Load("MyProject.Service")).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces().InstancePerLifetimeScope();
}
}
public class EfModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType(typeof(MyDataContext)).As(typeof(IMyContext)).InstancePerLifetimeScope();
}
}
As you see we also call AutoMapper to configure the different maps.
Then in our controllers we have this.
public class LinksController : Controller
{
private readonly ILinkService _linkService;
public LinksController(ILinkService linkService)
{
_linkService = linkService;
}
public ActionResult Index()
{
var links = _linkService.GetAllLinks();
return View(links.ToMappedPagedList<LinkDto, LinksListModelAdmin>());
}
...
public ActionResult Create(LinksEditModelAdmin insertedModel)
{
try
{
if (!ModelState.IsValid) return View("Create", insertedModel);
var insertedEntity = Mapper.Map<LinkDto>(insertedModel);
_linkService.Create(insertedEntity);
return RedirectToAction("Index");
}
catch (Exception ex)
{
throw ex;
}
}
}
Well, this is it...I hope this can be useful for somebody...and also I hope we can have a little help with the questions we have.
1) Although we are separating database from the web project we do need a reference in the web project to initialize the database and also to inject dependencies, is this correct?
2) Is it correct the approach we have done having our Entities->DTOs->ViewModels? It's a little more work but we have everything separated.
3) In the Service project, when we need to reference a different entity than the main one we are using in the service, is it correct to call Context.Entity?
For example, if we need to retrieve also data from the News entity in the links service, is it correct to call "Context.News.Where..."?
4) We do have a little problem with Automapper and EF proxy, because when we call "Dbset" to retrieve data, it gets a "Dynamic proxies" object so Automapper can't find the proper map so, in order to work, we have to set ProxyCreationEnabled = false in the DataContext definition. This way we can get an Entity in order to map it to the DTO. This disables LazyLoading, which we don't mind, but is this a correct approach or there is a better way to solve this?
Thanks in advance for your comments.
For Question no. 2
Entities->DTOs->ViewModels? is good approach
because you are doing the clean separation, the programmer can work together with ease.
The person who design ViewModels, Views and Controllers don't have to worry about the service layer or the DTO implementation because he will make the mapping when the others developpers finish their implementation.
For Question no. 4
When the flag ProxyCreationEnabled is set to false, the proxy instance will not be created with creating a new instance of an entity. This might not be a problem but we can create a proxy instance using the Create method of DbSet.
using (var Context = new MydbEntities())
{
var student = Context.StudentMasters.Create();
}
The Create method has an overloaded version that accepts a generic type. This can be used to create an instance of a derived type.
using (var Context = new MydbEntities())
{
var student = Context.StudentMasters.Create<Student>();
}
The Create method just creates the instance of the entity type if the proxy type for the entity would have no value (it is nothing to do with a proxy). The Create method does not add or attach the entity with the context object.
Also i read some where if you set ProxyCreationEnabled = false the child element will not loaded for some parent object unless Include method is called on parent object.

How to filter breeze.webapi returned entities from the server

I have a standard breeze web-server which exposes the Project
[HttpGet]
public IQueryable<Project> Projects()
{
return _db.Context.Projects;
}
How can i prevent a Project with NoLongerExist=true from begin included in queries returned to the JavaScript client from here affecting the functionality of the breezejs client?.. um i would also like to hide this property also, people wont like to see that their projects are not actually deleted!
you can try this on your breeze controller...
public IQueryable<Project> Projects()
{
return _db.Context.Projects.Where(o => o.NoLongerExist == true);
}
prevent json serialization of the NoLongerExist property using data annotations on your model by doing this, i'm assuming you are using EF6 with JSON.NET on your backend...
[Table("Project")]
public partial class Project
{
public Project()
{
}
public int id { get; set; }
[JsonIgnore]
public bool NoLongerExist { get; set; }
}

OptionsModel dependency injection in vNext console application

I have a vNext console application where one of my classes takes the OptionsModel<T> POCO configuration settings class.
I am unable to get the POCO settings class resolved and injected into my RabbitMqConnection class below.
Setting up the ServiceProvider is not the issue, it's the resolution of the settings class.
Note, this is a vNext console application (not an mvc6 app).
My second question is, and I understand constructor arguments should be kept minimal, but is it not best to pass the two strings as constructor arguments rather than an IOptions class as the former method is more descriptive of what the RabbitMqConnection class requires? If so, how is this best injected from the class that defined the mappings (Program.cs file in example below)
public class RabbitMqConnection
{
public string HostName { get; set; }
public string UserName { get; set; }
public RabbitMqConnection(IOptions<MessagingSettings> settings)
{
HostName = settings.Value.HostName;
UserName = settings.Value.UserName;
}
}
public class MessagingSettings
{
public string HostName { get; set; }
public string UserName { get; set; }
}
appsettings.json
{
"MessagingSettings":{
"HostName":"localhost",
"Username":"guest"
}
}
public void ConfigureServices(IServiceCollection services)
{
// tried registration a number of ways as below
services.Configure<MessagingSettings>(Configuration.GetSection("MessagingSettings"));
services.Configure<MessagingSettings>(Configuration);
// attempt 1 - get runtime error saying cant resolve IOptions<MessageSettings>
services.TryAdd(ServiceDescriptor.Singleton<RabbitMqConnection, RabbitMqConnection>());
// attempt 2 - same as above, when i breakpoint on messagingSettings, all the values in the object are null
services.TryAdd(ServiceDescriptor.Singleton<RabbitMqConnection>(factory =>
{
// instead of injecting the MessageSettings, pass through the string values (constructor omitted for clarity)
var messagingSettings = Configuration.Get<MessagingSettings>();
return new RabbitMqConnection(messagingSettings.HostName, messagingSettings.UserName);
}));
}
var conn = ServiceProvider.GetRequiredService<RabbitMqConnection>();
You need to call services.AddOptions()

How to use a custom class in Odata v4 instead of class from designer.cs

C# Web.Api Odata APplication
I’m implementing Odata V4 for the first time and would like to use my own custom class instead of the data class from the designer.
Here is what I did:
I created a Data project in Visual Studios and added my SQL Linq data table “Video”
I created the data context as follows:
public class VideoDataContext : DbContext
{
public VideoDataContext(): base("name=VideoData")
{
DbSet<VideoEf> Videos { get; set; }
}
And my custom class as follows:
[Serializable]
[DataContract]
public class VideoEf : Repository
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Isrc { get; set; }
}
And model builder:
public Microsoft.OData.Edm.IEdmModel GetEdmModel()
{
ODataModelBuilder builder = new ODataConventionModelBuilder();
EntityTypeConfiguration<VideoEf> titleType = builder.EntityType<VideoEf>();
builder.EntitySet<VideoEf>("Video");
return builder.GetEdmModel();
}
And in my video controller:
public class VideoController : ODataController
{
VideoDataContext db = new VideoDataContext ();
[EnableQuery(PageSize = 20, MaxExpansionDepth = 5)]
public IHttpActionResult Get()
{
return Ok(db.Videos.AsQueryable());
}
When I make the call to get the video entities I keep getting a ” 406 Not Acceptable” error message
How can I ensure that the data returned from the database is mapped to my custom model ?
Is my model builder correct?
what could be causing the above error?
You don't need to return IQueryable because you have EnableQuery attribute, just return DbSet.
You also don't need any wcf attribute and EntityTypeConfiguration<VideoEf> titleType = builder.EntityType<VideoEf>();
Then it should just work.
Hope it helps.
Edit
My mistake for IQueryable, I also use it.

S#arp Architecture Fluent mapping for self referencing entity (Tree structure)

I've come up against a problem in converting my Fluent NH mapping to Sharp Architecture. I like the platform for it's ease, however it seems to handle entity mappings slightly differently to pure Fluent NH.
I have a Entity 'Category' that is a simple tree structure. I have to override the auto-mapping as there is a M:M property that I need to add in (not included in code below).
When I create tests on the repository, the GetAll method returns all Categories as it should, however the Children property just infinitely loops itself. i.e. the list of children for each category only contains itself, in and unending loop.
/// The Entity ///
public class Category : Entity
{
public Category()
{
InitMembers();
}
/// <summary>
/// Creates valid domain object
/// </summary>
public Category(string name)
: this()
{
Name = name;
}
/// <summary>
/// Creates valid domain object
/// </summary>
public Category(string name, int depth)
: this()
{
Name = name;
Depth = depth;
}
private void InitMembers()
{
Children = new List<Category>();
}
[DomainSignature]
[NotNullNotEmpty]
public virtual string Name { get; protected set; }
[DomainSignature]
public virtual int Depth { get; protected set; }
public virtual Category Parent { get; set; }
public virtual IList<Category> Children { get; private set; }
public virtual void AddChild(Category category)
{
category.Parent = this;
Children.Add(category);
}
}
/// The Mapping ///
public class CategoryMap : IAutoMappingOverride<Category>
{
public void Override(AutoMap<Category> mapping)
{
mapping.Id(x => x.Id, "CategoryId")
.WithUnsavedValue(0)
.GeneratedBy.Identity();
mapping.Map(x => x.Name).WithLengthOf(50);
mapping.Map(x => x.Depth);
mapping.HasMany<Category>(x => x.Children)
.Inverse()
.Cascade.All()
.KeyColumnNames.Add("Parent_id")
.AsBag();
}
}
/// The Data Repository Tests ///
[TestFixture]
[Category("DB Tests")]
public class CategoryRepositoryTests : RepositoryTestsBase
{
private readonly IRepository<Category> _repository = new Repository<Category>();
protected override void LoadTestData()
{
CreatePersistedCategory("Root 1");
CreatePersistedCategory("Root 2");
CreatePersistedCategoryWithChildren("Level 1", "Level 2", "Level 3");
}
[Test]
public void CanGetAllCategories()
{
var categories = _repository.GetAll();
categories.ShouldNotBeNull();
categories.Count.ShouldEqual(5);
}
[Test]
public void CanGetCategoryById()
{
var category = _repository.Get(1);
category.Name.ShouldEqual("Root 1");
category.Depth.ShouldEqual(1);
}
[Test]
public void CanGetCategoryChildren()
{
var category = _repository.Get(3);
category.Name.ShouldEqual("Level 1");
category.Depth.ShouldEqual(1);
category.Children.ShouldNotBeNull();
category.Children.Count.ShouldEqual(1);
category.Children[0].Name.ShouldEqual("Level 2");
category.Children[0].Depth.ShouldEqual(2);
category.Children[0].Children.ShouldNotBeNull();
category.Children[0].Children.Count.ShouldEqual(1);
category.Children[0].Children[0].Name.ShouldEqual("Level 3");
category.Children[0].Children[0].Depth.ShouldEqual(3);
}
private void CreatePersistedCategory(string categoryName)
{
var category = new Category(categoryName, 1);
_repository.SaveOrUpdate(category);
FlushSessionAndEvict(category);
}
private void CreatePersistedCategoryWithChildren(string category1, string category2, string category3)
{
var cat1 = new Category(category1, 1);
var cat2 = new Category(category2, 2) { Parent = cat1 };
var cat3 = new Category(category3, 3) { Parent = cat2 };
cat1.AddChild(cat2);
cat2.AddChild(cat3);
_repository.SaveOrUpdate(cat1);
FlushSessionAndEvict(cat1);
}
}
Managed to work it out, after much Mapping tweaking. The Auto-mapping stuff although very cool requires some understanding. RTFM for me...
Right you are, I hadn't yet discovered or understood the Auto-mapping conventions: TableNameConvention, PrimaryKeyConvention, and specifically HasManyConvention. The default S#arp code likes to pluralise its database tables, and have Id columns with the table name prefixed, i.e. CategoryId.
I don't like to pluralise, and I like consistent Id columns, 'Id' suffices. And my foreign key references were different style to, I like Category_id.
public class HasManyConvention : IHasManyConvention
{
public bool Accept(IOneToManyCollectionInstance oneToManyPart)
{
return true;
}
public void Apply(IOneToManyCollectionInstance oneToManyPart)
{
oneToManyPart.KeyColumnNames.Add(oneToManyPart.EntityType.Name + "_id");
}
}
public class PrimaryKeyConvention : IIdConvention
{
public bool Accept(IIdentityInstance id)
{
return true;
}
public void Apply(IIdentityInstance id)
{
id.Column("Id");
}
}
However now this all works a treat but I now have a problem with Many-to-many mappings. It seems S#arp doesn't quite support them yet. My mapping overrides don't seem to work, nothing gets inserted into my mapping table in the database.
See: S#arp Architecture many-to-many mapping overrides not working
I was not able to solve this using fluent conventions and from what I have seen searching around this currently can't be done using conventions. Fluent assumes that a self-referencing tree like this is many-to-many, so in your case I assume you are trying to map a many-to-many relationship and so there should be no problem.
In my case I needed to map it as many-to-one (for a strict hierarchy of nested comments and replies). The only way I could figure out to do this was setting an override for the parent-child class to map that relationship. Fortunately it is very easy.
I would love to know if there is a way to successfully map many-to-one like this with conventions though.

Resources