EF ComplexType DbModelBuilder Dictionary example - c#

I'm using a EF DbSet<FiveMinStockHistory>. And now, I need a code snippet showing how to implement the EF6+ method DbContext.OnModelCreating(DbModelBuilder modelBuilder) to populate a code-first database. I could not find any good examples.
public class FiveMinStockHistory
{
public int Id { get; set; }
public Dictionary<string, string> Meta_Data { get; set; }
public Dictionary<string, TimeSeries> Lhocv { get; set; }
}
public class TimeSeries
{
public decimal Open { get; set; }
public decimal High { get; set; }
public decimal Low { get; set; }
public decimal Close { get; set; }
public double Volume { get; set; }
}
Thanks!!!

You can seed a database in many ways. Usually, you want it to have happened on startup. So you create a DbInitializer.cs class that has a static initialize method.
public static void Initialize(MyDbContext context)
{
context.Database.EnsureCreated();
// Create the objects you want to insert into DbContext.
// Write it to a variable, for example, "var ExampleData".
// Add example data.
context.FiveMinStockHistory.Add(ExampleData)
context.SaveChanges();
}
Then you could just run it on startup:
public void Configure(IApplicationBuilder app, MyDbContext context)
{
MyDatabaseInitializer.Initialize(context);
}
Easy peasy. Good luck!

Related

Post a decimal value in database using ASP.NET Web API

I am working on an ASP.NET Web API project and I have a database that I am using, and the model that I am working on look something like this
public class PAY
{
public int ID { get; set; }
public string PAY_CODE { get; set; }
public Nullable<decimal> PAY_CASH { get; set; }
}
and I have a simple post method look like this:
[HttpPost]
public string AddPayROW(string PAY_CODE, decimal PAY_CASH,)
{
var PAY = new PAY()
{
PAY_CODE = PAY_CODE,
PAY_CASH = PAY_CASH,
};
db.PAY.Add(PAY);
db.SaveChanges();
return "Row added successfully";
}
My problem is kind of weird but when I post this decimal value to the table the last number is zero
For example, if I tried to post 1.999 will be saved like this 1.990
I am using SQL Server and the datatype is decimal(16, 3)
How can I fix this problem?
On your OnModelCreating function add this code,
modelBuilder.Entity<PAY>().Property(x => x.PAY_CASH).HasPrecision(18,3);
Hope it works.
Edit : Do you have DbContext like this? For example;
public partial class DBO : DbContext
{
public DBO()
: base("ConStrEtc")
{ }
public virtual DbSet<PAY> PAYs { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<PAY>().Property(x => x.PAY_CASH).HasPrecision(18, 3);
}
}
public class PAY
{
public int ID { get; set; }
public string PAY_CODE { get; set; }
public Nullable<decimal> PAY_CASH { get; set; }
}

ASP.NET Core relation is in database but is not retrieved

I am new to ASP.NET Core and I am trying to setup basic relationship with EntityFramework Core. I have a NavigationCategory class that has 1:M relationship with WebPage class. The relationship is understood by my DB (It has a foreign key) but when retrieving the WebPage from repository, it has no NavigationCategory, even though it has NavigationCategoryId set.
public class WebPage : BaseEntity
{
private string _route;
public string Title { get; set; }
public string Body { get; set; }
[ForeignKey("NavigationCategory")]
public long NavigationCategoryId { get; set; }
public NavigationCategory NavigationCategory { get; set; }
public WebPage()
{
}
}
public class NavigationCategory : BaseEntity
{
public string Title { get; set; }
public IEnumerable<WebPage> WebPages { get; set; }
public NavigationCategory()
{
}
}
This is simple BaseEntity:
public class BaseEntity
{
public long Id { get; set; }
}
This is my DB context:
public class AppDataContext : DbContext
{
public DbSet<Employee> Employees { get; set; }
public DbSet<KinderClass> KinderClasses { get; set; }
public DbSet<Feed> Feeds { get; set; }
public DbSet<NavigationCategory> NavigationCategories { get; set; }
public DbSet<WebPage> WebPages { get; set; }
public AppDataContext(DbContextOptions<AppDataContext> options) : base(options)
{
Database.EnsureCreated();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<WebPage>()
.HasOne(wp => wp.NavigationCategory)
.WithMany(c => c.WebPages)
.HasForeignKey(wp => wp.NavigationCategoryId);
}
}
You need to explicitly include any navigation property you want included when you fetch entities using EF Core. For example, update your query as follows:
var webpage = dbContext.WebPages
.Include(w => w.NavigationCategory)
.FirstOrDefault();
Note, you need these two namespaces, at minimum:
using Microsoft.EntityFrameworkCore;
using System.Linq;
Learn more about loading related data and why lazy loading shouldn't be used in web apps.

What's the correct way to use Effort with Entity Framework 6?

I'm trying to get some test code working using the Effort data provider with Entity Framework 6. What I'm trying to do seems like it should be the absolute simplest use-case, but I'm just not able to get things to work.
Here is my DbContext class:
public class CcdReductionFrameCatalogue : DbContext
{
public CcdReductionFrameCatalogue()
: this("name=CcdReductionFrameCatalogue") {}
public CcdReductionFrameCatalogue(string connectionString) : base(connectionString) {}
public CcdReductionFrameCatalogue(DbConnection connection) : base(connection, true) {}
public virtual DbSet<CcdFrame> CcdFrames { get; set; }
}
The POCO entity is defined as:
public class CcdFrame : IEquatable<CcdFrame>
{
public CcdFrame()
{
AcquisitionTimeUtc = DateTime.UtcNow;
}
public int Id { get; set; }
public string Location { get; set; }
[FitsKeyword("INSTRUME")] public string CameraName { get; set; }
[FitsKeyword("EXPTIME")] public double ExposureTimeSeconds { get; set; }
[FitsKeyword("SET-TEMP"), FitsKeyword("CCD-TEMP")] public double TemperatureSetpoint { get; set; }
[FitsKeyword("NAXIS1")] public int SizeX { get; set; }
[FitsKeyword("NAXIS2")] public int SizeY { get; set; }
[FitsKeyword("XBINNING")] public int BinningX { get; set; }
[FitsKeyword("YBINNING")] public int BinningY { get; set; }
[FitsKeyword("IMAGETYP")] public string FrameType { get; set; }
[FitsKeyword("DATE-OBS")] public DateTime AcquisitionTimeUtc { get; set; }
[FitsKeyword("XORGSUBF")] public int SubframeOriginX { get; set; }
[FitsKeyword("YORGSUBF")] public int SubframeOriginY { get; set; }
// IEquatable implementation elided for clarity
}
The [FitsKeyword] attribute is a custom attribute that I've defined and should not have any bearing on Entity Framework.
In my unit tests, I set up my data connection like this, as shown in the Effort quick-start guide:
Connection = DbConnectionFactory.CreateTransient();
Repository = new CcdReductionFrameCatalogue(Connection);
As soon as I use any LINQ on the DbSet, I get stupid meaningless error messages. For example, when I pass my repository into this trivial code:
static void AddOrUpdate(CcdFrame newFrame, CcdReductionFrameCatalogue repository)
{
var existingFrames = from frame in repository.CcdFrames
where frame.Equals(newFrame)
select frame;
Console.WriteLine(existingFrames.Count());
// ...never gets past here
When I run this code, I get:
System.NotSupportedExceptionUnable to create a constant value of type 'TA.ReductionManager.DomainObjects.CcdFrame'. Only primitive types or enumeration types are supported in this context.
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.EqualsTranslator.TypedTranslate(ExpressionConverter parent, BinaryExpression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call, ref DbExpression source, ref DbExpressionBinding sourceBinding, ref DbExpression lambda)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.OneLambdaTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.AggregateTranslator.Translate(ExpressionConverter parent, MethodCallExpression call)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq)
at System.Data.Entity.Core.Objects.ELinq.ExpressionConverter.Convert()
at System.Data.Entity.Core.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption)
at System.Data.Entity.Core.Objects.ObjectQuery`1.c__DisplayClass7.b__6()
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction(Func`1 func, IDbExecutionStrategy executionStrategy, Boolean startLocalTransaction, Boolean releaseConnectionOnSuccess)
at System.Data.Entity.Core.Objects.ObjectQuery`1.c__DisplayClass7.b__5()
at System.Data.Entity.Core.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption)
at System.Data.Entity.Core.Objects.ObjectQuery`1..GetEnumerator>b__0()
at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
at System.Linq.Enumerable.Single(IEnumerable`1 source)
at System.Linq.Queryable.Count(IQueryable`1 source)
at TA.ReductionManager.Specifications.FitsImporter.AddOrUpdate(CcdFrame newFrame, CcdReductionFrameCatalogue repository) in FitsImporter.cs: line 38
at TA.ReductionManager.Specifications.FitsImporter.ImportCollection(IEnumerable`1 collection, CcdReductionFrameCatalogue repository) in FitsImporter.cs: line 29
at TA.ReductionManager.Specifications.when_importing_fits_files_into_the_catalogue_and_there_are_no_subdirectories.b__5() in FileEnumeratorSpecs.cs: line 27
Now this is mind-numbingly simple LINQ code, what am I missing here?
You cannot compare custom objects in a LINQ query. You should compare only primitive type (int, string, etc).
var existingFrames = from frame in repository.CcdFrames
where frame.Id == newFrame.Id
select frame;
You can get some info here: Only primitive types or enumeration types are supported in this context

The operation failed because an index or statistics with name 'IX_AuctionId' already exists on table 'Bids'

This question is related to this question which was never answered. I have a more real world example here though - so hoping for some help.
I have an auction, bid and auctiondetail(a flattened table) class.
I am trying to include my bids in the auction as well as auctiondetail table, auction and auctiondetail have the same PK
using System.Collections.ObjectModel;
using System.ComponentModel.DataAnnotations;
namespace OnCall.VirtualWarehouse.Data.Models.Auctions
{
using System;
public class AuctionCopy
{
public Guid AuctionCopyId { get; set; }
public virtual Collection<BidCopy> BidCopies { get; set; }
}
public class BidCopy
{
public Guid BidCopyId { get; set; }
public Guid AuctionCopyId { get; set; }
public AuctionCopy AuctionCopy { get; set; }
}
public class AuctionDetailCopy
{
[Key]
public Guid AuctionCopyId { get; set; }
public virtual Collection<BidCopy> BidCopies { get; set; }
}
}
Here's my DBContext:
public class DataContext : DbContext
{
static DataContext()
{
Database.SetInitializer(new DropCreateIfChangeInitializer());
}
public DataContext()
{
Configuration.ProxyCreationEnabled = false;
}
public IDbSet<AuctionCopy> AuctionCopy { get; set; }
public IDbSet<BidCopy> BidCopy { get; set; }
public IDbSet<AuctionDetailCopy> AuctionDetailCopy { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
}
public void Seed(DataContext context)
{
}
}
When generating the database, I get
The operation failed because an index or statistics with name 'IX_AuctionId' already exists on table 'Bids'.
Any ideas how I can get this to work?
The bug come from EF4.3 (and 4.3.1).
It should be fixed for the next release.
Have a look on Unhandled Exception after Upgrading to Entity Framework 4.3.1. They purpose a workaround using migration system.

How can I bind my MVC Model to a different table

This seems like an easy question but I can't seem to find the answer.
I have a Model that looks like this ...
public class Application
{
public int Id { get; set; }
public string Title { get; set; }
public string LeadProgrammer { get; set; }
public string ConnectionStringCode { get; set; }
}
public class ApplicationDBContext : DbContext
{
public DbSet<Application> Applications { get; set; }
}
My actual table name is DBA_APPLICATIONS ... the model is, of course, just looking for dbo.Applications. How can I change this routing to the actual table?
Add this in your ApplcationDBContext class.
public class ApplicationDBContext : DbContext
{
public DbSet<Application> Applications { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Application>().ToTable("DBA_APPLICATIONS");
// otherwise EF assumes the table is called "Applications"
}
}

Categories