Peculiar Issue When Using Expressions and (Web) Console Application - c#

I ran into an issue the other day that I first believed to be an issue with Entity Framework. I posted a question about it the other day here. Since then, I have determined that this issue is not related to Entity Framework.
Consider the following classes:
public abstract class ModelBase
{
public Guid Id { get; set; }
}
public class User : ModelBase
{
public string Username { get; set; }
}
public abstract class ModelBaseConfiguration<T> where T : ModelBase
{
public virtual void Configure()
{
ConfigureGuidProperty(e => e.Id);
}
protected void ConfigureGuidProperty(Expression<Func<T, Guid>> expression)
{
Debug.WriteLine(expression);
}
protected void ConfigureStringProperty(Expression<Func<T, string>> expression)
{
Debug.WriteLine(expression);
}
}
public class UserConfiguration : ModelBaseConfiguration<User>
{
public override void Configure()
{
base.Configure();
ConfigureStringProperty(e => e.Username);
}
}
If I add the following code to the Main method of an old Console Application project (the one located under the Windows node in VS2015):
UserConfiguration configuration = null;
configuration = new UserConfiguration();
configuration.Configure();
...and execute it, I get the following output in the debug window:
e => e.Id
e => e.Username
This is what I expect.
Now, if I use the exact same code as listed above in a new ConsoleApplication project (the one located under the Web node in VS2015) and execute it, I get the following output in the debug window:
e => Convert(e).Id
e => e.Username
As you can see, the first line of output is different than before. This is what is causing issues with Entity Framework.
I have discovered that the difference is the project type, being that the code is exactly the same in both scenarios. What I am trying to figure out is why. Why is there an attempted conversion in the expression of the second scenario? Is there something I have been missing for some time now? Is this an issue with the new project type? I am trying to educate myself so that I can adjust if necessary.

This issue is corrected after installing the ASP.NET 5 RC1 update.

Related

How do I implement a simple "complex type" in Entity Framework Core 2/C#?

I'm using Entity Framework and .Net Core 2.0 for the first time (I'm also pretty new to C#, but I've been using the traditional .Net Framework & VB since version 1... so I'm no newbie to .Net development), and I've already run into a problem creating my database.
Take this simple scenario: I want to store some information about some electric pumps. Two of the properties are a min/max type range, so I've implemented these as a simple class, thus:
public class Pump
{
[Key]
public int pumpId { get; set; }
public string pumpName { get; set; }
public int pumpControlChannel { get; set; }
public MinMax normalCurrent { get; set; }
public MinMax normalFlowRate { get; set; }
}
[ComplexType]
public class MinMax
{
public int min { get; set; }
public int max { get; set; }
}
As you can see, I've tried the [ComplexType] decorator, to no avail.
Anyway, now create a dead simple DBContext class to manage my Pumps class. I'm using Sqlite:
public class EFDB : DbContext
{
public DbSet<Pump> pumps { get; private set; }
private static DbContextOptions GetOptions(string connectionString)
{
var modelBuilder = new DbContextOptionsBuilder();
return modelBuilder.UseSqlite(connectionString).Options;
}
public EFDB(string connectionString) : base(GetOptions(connectionString)) { }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
try
{
// modelBuilder.ComplexType<MinMax>(); // ComplexType not recognised
base.OnModelCreating(modelBuilder);
}
catch (Exception ex)
{
System.Diagnostics.Debugger.Break();
}
}
}
and lastly a simple static class to call it (I embeded it in a bigger program... to duplicate this problem you could just stick the code lines into program.cs):
public static class TryMe
{
public static void MakeMeFail()
{
using (var db = new EFDB("FileName=C:\\temp\\test_effail.db"))
{
try
{
db.Database.EnsureCreated();
}
catch (Exception ex)
{
System.Diagnostics.Debugger.Break(); // If we hit this line, it fell over
}
}
System.Diagnostics.Debugger.Break(); // If we hit this line, it worked.
}
}
Just call TryMe.MakeMeFail(), the code fails at db.Database.EnsureCreated().
From everything I've read, [ComplexType] should do what I want... but it Just Doesn't. Nor can I find modelBuilder.ComplexType<T> anywhere.
It may just be a library reference I'm missing...? The above code uses the following:
using System;
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
However, NONE of the documentation/examples I can find anywhere show which libraries need referencing!
Thanks in advance.
[PS: Apologies to those who already saw this question, I'm using EF Core 2.0, NOT EF6]
Typical... it's always the way, isn't it? 5 minutes after posting, you discover the answer to your own question....
The answer, in this case, can be found here:
https://learn.microsoft.com/en-us/ef/core/modeling/owned-entities
EF Core calls this sort of entity an "owned" entity, rather than a "complex type".
Simply adding these lines to `OnModelCreating' fixed the issue:
modelBuilder.Entity<Pump>().OwnsOne(p => p.normalCurrent);
modelBuilder.Entity<Pump>().OwnsOne(p => p.normalFlowRate);
The database now creates (correctly, I think, I haven't verified that yet).

What happened to HasColumnName for EF Core?

So I am trying to map an internal property to my database and according to this article online this is how you are supposed to do it. The other resources that I found also tell me to do the same thing. For whatever reason the method doesn't exist and I can't find online what they renamed it too or if they just removed the method.
Here is my code:
public class Criteria : DbEntity
{
internal string _Condition { get; set; }
[NotMapped]
public Condition Condition
{
get
{
return string.IsNullOrEmpty(_Condition) ? null : JsonConvert.DeserializeObject<Condition>(_Condition);
}
set
{
_Condition = JsonConvert.SerializeObject(value);
}
}
}
protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Criteria>().Property(b => b._Condition);//.HasColumnName("Condition"); <-- this doesn't exist...
}
Had to install Microsoft.EntityFrameworkCore.Relational to fix the issue.
Edit:
Credit goes to Ivan Stoev for finding this out
If you're using SQL Server and using Core 3.1x, you can also fix this by installing Microsoft.EntityFrameworkCore.SqlServer.

TPH EF6.0: Cannot calculate the value of expression

I have 3 classes inherited from an abstract base class:
abstract class PortTaskStep{
public Guid TaskID { get; set; }
[ForeignKey("TaskID")]
public virtual PortChangeTask PortChangeTask { get; set; }
public virtual String CompleteStep() { return string.Empty;}
}
class PortTaskStep_Add:TaskStep{}
class PortTaskStep_Modify:TaskStep{}
class PortTaskStep_Delete:TaskStep{}
public class HncNetScanContext : DbContext
{
public DbSet<PortTaskStep> PortTaskSteps { get; set; }
}
When I try to get data from table 'PortTaskSteps', the query returns :
cannot calculate the value of the expression
Some more details:
public class PortChangeTask{
public ICollection<PortTaskStep> PortTaskSteps { get; set; }
public Boolean CompleteTask(){
foreach (var portTaskStep in PortTaskSteps)
{
portTaskStep.CompleteStep();
}
}
}
The Domain assembly contains the classes mentioned above are referenced by a web project and a web site. And when I debug the function in the web site, everything goes well.However, when I debug the same function in the web project, the results is null.
The Snapshot
For another scene tested in the Web Project:
As shown in the Snapshot, I try to get "PortTaskSteps". And the result is null. However, after I uncomment the "textQuery", the result is a list of PortTaskStep.
The Snapshot
I think something is going wrong in webconfig or environment of the Web Project, however, I cannot figure out the point...:(
How can I resolve the problem?
Thanks!
Perhaps the right translation might be "Could not evaluate expression". If so, then most likely it's the problem with Visual Studio. Try to delete all your breakpoints from solution and reinsert them. If that doesn't help you, check this link: Visual Studio 2013 'Could not evaluate Expression' Debugger Abnormality.
If the problem for you appears always on both retrieving data and trying to see it in the debug mode then you might want to check your configuration (maybe you've missed mapping or something important for this table).

Is it possible to run C# on Up and Down migrations in Entity Framework?

We have a number of tables that contain JSON data. This data will need to be migrated from time to time. These JSON manipulations will likely be to complex to do directly in SQL. We would like to run C# to migrate this data. As far as I know there is no way to do this in the framework natively.
We tried using the DbMigrator class to get the applied migrations and the Seed method in the DbMigrationsConfiguration to then run the C# migrations based on the diff. Although this works for Up, unfortunately Seed isn't called on Down. See code below.
public abstract class CodeDbMigrationsConfiguration<TContext> : DbMigrationsConfiguration<TContext> where TContext : DbContext
{
readonly string[] _InitialDbMigrations;
protected IDictionary<string, DbCodeMigration<TContext>> CodeMigrations { get; private set; }
public CodeDbMigrationsConfiguration()
{
_InitialDbMigrations = new DbMigrator(this)
.GetDatabaseMigrations()
.ToArray();
CodeMigrations = new Dictionary<string, DbCodeMigration<TContext>>();
}
protected override void Seed(TContext context)
{
if (CodeMigrations.Count > 0)
{
var currentMigrations = new DbMigrator(this)
.GetDatabaseMigrations()
.ToArray();
var update = GetMigrationUpdate(_InitialDbMigrations, currentMigrations);
DbCodeMigration<TContext> migration;
foreach (var name in update.Down)
if (CodeMigrations.TryGetValue(name, out migration))
migration.Down(context);
foreach (var name in update.Up)
if (CodeMigrations.TryGetValue(name, out migration))
migration.Up(context);
}
base.Seed(context);
}
//...
}
I thought about inheriting from DbMigrator and just wrapping the Update method but I can't find a way of forcing the tools (Visual Studio and Migrate.exe) to use my DbMigrator. Anyone have any ideas on how to run C# code on migrating up and down?

Error creating MVC 4 controller

I'm getting an error "Unable to retrieve Metadata for "TeamAssignment.Models.Test. Unable to cast object of type "System.Data.Entity.Core.Objects.ObjectContext" to type "System.Data.Objects.ObjectContext."
This is happening whenever I try to create a controller with action/views with the code first entity framework. I'm trying it with a simple test class that's not related to my project and even that is not getting through.
namespace TeamAssignment.Models
{
public class Test
{
[Key]
public int id { get; set; }
public string test { get; set; }
}
public class testDBContext : DbContext
{
public DbSet<Test> testing { get; set; }
}
}
Am I being retarded here or is something wrong with my overall program? I was having some issues with TFS earlier and I'm trying to determine if its related to that.
Sounds like you recently upgraded to EF6.
Unfortunately the MVC 4 scaffolding tools are not compatible with EF6 and there's nothing you can do except upgrade to MVC5 (if possible).

Categories