I'm an experienced php developer and am attempting my hand at learning Microsoft Entity Framework. My backend Database is Oracle and I'm using ODP.Net as my connection. I've installed VS2019 Community and am working through several tutorials.
Oracle Entity Framework Core Introduction
Entity Framework Best Practices
Microsoft Create a Data Access Layer
EntityFrameworkCore
I'm struggling with trying to have my C# library (DAL) work well with my C# winforms projects. My DAL is a .NET Standard 2.0 project and my winforms projects is .NET Framework 4.7.2. My solution is setup as follows.
C# Solution
Project 1 - C# Library (DAL) - .NET Standard 2.0
Nuget Dependencies
Microsoft.EntityFrameworkCore.Design (2.2.6)
Microsoft.EntityFrameworkCore.Tools (2.2.6)
Oracle.EntityFrameworkCore(2.19.60)
Project 2 - C# Winforms - .NET Framework 4.7.2
Nuget Dependencies
Microsoft.EntityFrameworkCore(2.2.6)
Oracle.EntityFrameworkCore(2.19.60)
Oracle.ManagedDataAccess.Core (2.19.60)
Code pieces of code are in the DAL (project 1)
DbContext
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseOracle(#"<myConnString>");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfiguration(new PlatePurchaseOrderConfiguration());
}
public DbSet<PlatePurchaseOrder> LtPurchaseOrders { get; set; }
}
ModelConfiguration
class PlatePurchaseOrderConfiguration : IEntityTypeConfiguration<PlatePurchaseOrder>
{
public void Configure(EntityTypeBuilder<PlatePurchaseOrder> builder)
{
builder.HasKey(t => t.Id);
}
}
Model
public class PlatePurchaseOrder
{
public int Id { get; set; }
public bool IsExpeditied { get; set; }
public DateTime ExpectedReturnDate { get; set; }
}
This is the code behind the startup winforms (project 2)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
var context = new PlatePurchaseOrderContext();
var query = context.LtPurchaseOrders.ToList();
}
}
And upon running my code I get, an error at the .ToList() command of
Could not load file or assembly 'System.Diagnostics.DiagnosticSource, Version=4.0.3.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51
I have to imagine that I'm mixing projects and .NET components probably messing things up. Is there a good way around this? What should I be doing to correctly setup this Solution?
Related
I have two libraries - the first is in .NET Framework 4.6.1, while the second is in .NET Standard 2.0. (The second one depends on the first one)
The .NET Framework 4.6.1 contains the following class
public class Class_Framework : IValidatableObject
{
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
Console.WriteLine();
return null;
}
}
then I am trying to consume that class in my second .NET Standard 2.0 library:
interface IStandardInterface
{
string AProperty { get; set; }
}
class Class_Standard : Class_Framework, IStandardInterface
{
public string AProperty { get; set; }
}
public class MainStandardClass
{
public void AMethod()
{
IStandardInterface anInstance = new Class_Standard();
}
}
I cannot compile this code, because of the following error:
The type 'IValidatableObject' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
I am awared that there is no DataAnnotations library in .NET standard so I used NuGet System.ComponentModel.Annotations in both .NET Standard and .NET Framework library. The strangest thing is that if I change
IStandardInterface anInstance = new Class_Standard();
to
var anInstance = new Class_Standard();
then everything is OK. Do you have any suggestion how/if it is possible to inherits a class that implements IValidatableObject from .NET Framework library? Thank you
Not doable, period. A netstandard 2.0 library can only inherit from a netstandard 2.0 library, not a full .NET library.
This is per definition.
You will either have to split class hierarchies or move your other library over. We do not know enough for recommending a decent approach here.
I seem to be having a hard time finding the information I need to implement EF Core. I've read a lot of articles, and watched videos such as Getting Started with Entity Framework Core [1 of 5]. But none of these articles and videos assume a Razor Pages project created with the latest version of Visual Studio (16.3.6).
I'm much prefer (and am already familiar with) database first, but Microsoft has decided we need to be code first.
So I manually created my entity classes and ran the Add-Migration command. (Note that 00000000000000_CreateIdentitySchema.cs was created by Visual Studio when I created the project.)
It runs successfully but creates an empty Migration class.
public partial class InitialTaskClasses : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
Is there anyway to have it incorporate my entity classes into the migration?
*Note that I've already done an update-database command, which added the entity classes to my database.
public DbSet<Area> Area{ get; set; }
public DbSet<Goal> Goal{ get; set; }
public DbSet<Task> Task{ get; set; }
This should go as properties inside your ApplicationDbContext
I am making a C# MVC application using Entity Framework 6.2.0 Everything was going fine until today when I tried to do some migrations.
I had no problem with migrating a week ago but I have no idea what might have caused the error in the package manager:
No DbContext was found in assembly 'Data'. Ensure that you're using
the correct assembly and that the type is neither abstract nor
generic.
I tried reinstalling Entity Framework and made sure that the "Default project" is the right one. I already have a context file that worked properly.
This is my GameContext.cs code:
public class GameContext :DbContext
{
public GameContext()
:base ("name=GameContext")
{
}
public DbSet<Game> Game { get; set; }
public DbSet<Account> Account { get; set; }
}
I need to find a way to fix this problem and manage to update my database.
You maybe need to select ProjectName.Data in project management console
Try adding your assembly name when registering the service, you can find assembly name by going to project properties.
services.AddDbContextPool<AppDbContext>
(
dbContextOptionsBuilder =>
{
dbContextOptionsBuilder.UseSqlServer("yourConnection",
optionsSqlServer => { optionsSqlServer.MigrationsAssembly("ADD_YOUR_ASSEMBLY_NAME");});
}
);
How to create or use ready Shims for .net framework 4.6.1 elements to port them (from .net framework 4.6.1) to .net core 2.0 / .net standard 2.0?
Some classes of interest:, it would be nice to have shims for classes like:
System.Windows.Threading.Dispatcher
or
System.ComponentModel.ItemPropertyInfo.Descriptor
even
System.Windows.Controls.MenuItem
and many more...
Context:
The application (the code) is not 100% well organized. Business logic is not 100% separated from UI logic. The answer "do refactoring first" is definitely a good answer. But in my case things are not 100% how they should ideally be.
Approximate example, a try to do it mannually:
System.Windows.Threading.Dispatcher is not implemented in Core 2.0.
One could try to add:
public enum DispatcherShimPriority
{
Background
//...
}
public interface DispaicherShim
{
void Invoke(Action action, DispatcherShimPriority prio);
void BeginInvoke(Action action, DispatcherShimPriority, prio);
}
Followed by two implementations of this interface:
public class DispatcherCore: DispaicherShim;
and
public class DispatcherFramework: DispaicherShim;
Followed by a a class (let's call it Shims) in a multitargeted project:
public static DispaicherShim CreateDispatcher()
{
#if NETCOREAPP2_0
return new DispatcherCore();
#else
return new DispatcherFramework();
#endif
}
The result is the shim, which could be used in different APIs.
Is this a correct approach?
Actually, creating such shims requires much routine work. I have a feeling that this work is not necessary to be performed. I have a feeling that there is a ready solution for this problem...
I'm aware of Microsoft.Windows.Compatibility package. The question is rather related to porting when WPF is involved with many wpf-specific elements. Those elements are not in Microsoft.Windows.Compatibility package, but, unfortunately, they are used across my assemblies, which are candidates for retargeting to .Net Core 2.0. I mean shimming those classes, which are not in Microsoft.Windows.Compatibility.
Ok, we have this Microsoft.Windows.Compatibility.Shims, but i'm not sure that it is useful in my case; especially after reading the following text:
Microsoft.Windows.Compatibility.Shims: This package provides
infrastructure services and shouldn't be referenced directly from
your code....
Upd: emphasizing that the final target is .net core 2.0
Upd2: the whole task is to port the major part of a WPF app to .net core (leaving working WPF app) for potential web-client. The major part contains .net framework elements which are not implemented for .net core.
Upd3: Couple of words about complete strategy: The more complete strategy is Shared projects, first approach in this article (#if) . There are 2 major steps in my strategy: one is to gradually port code, starting from base libraries and finnishing at top libraries, But with intense use of stubs and PlatformNotSupportedExceptions. The second step is to move from top libraries to base libraries substituting stubs and exceptions by .net core implementations, On demand (!) - no need to subsitute all stubs and exceptions.
Upd4 We have already split portable tests from non-portable tests (into two libs). It is very important that we run the tests during the porting process.
Moving from Standard .Net to .Net Core is not just an upgrade, you could almost call it a move to a new platform considering how things are put together. Moving to .Net core means learning and creating a new framework where existing code can be copied.
Due to the large differences between .Net core 1, 1.1, 2.0 and 2.1 The migration process form these has changed a lot, so there is no 1 size fits all "shim" and having some kind of wrapper or migration tool would be quickly made obsolete. Work needs to be done to migrate your code.
Some core OS APIs are similar but a lot of framework code has been moved or changed, so chasing like for like swaps might also be difficult. Its really worth doing some R&D to see where the differences are not to mention the use fo 3rd party libraries etc.
Following are at least satisfactory approaches:
Thanks Firda from Czech Republic . This is his answer
1) Generic shim is enough for me (snippets may help)
public abstract class Shim<TImpl>
{
internal TImpl It { get; }
protected Shim(TImpl it) { It = it; }
}
EXAMPLE:
public class DispatcherPriorityShim : Shim<
#if NETFULL
DispatcherPriority
#elif NETCORE
string
#endif
>
{
public DispatcherPriorityShim(string it)
#if NETFULL
: base((DispatcherPriority)Enum.Parse(typeof(DispatcherPriority), it))
#elif NETCORE
: base(it)
#endif
{ }
}
My sdk-style .csproj file to make clear about NETFULL and NETCORE:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><TargetFrameworks>netstandard2.0;netcoreapp2.0;net461</TargetFrameworks></PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0' OR '$(TargetFramework)' == 'netstandard2.0'">
<DefineConstants>NETCORE;</DefineConstants></PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net461'">
<DefineConstants>NETFULL;</DefineConstants></PropertyGroup>
</Project>
1.a) Visual Studio snippets
drv
#if NETFULL
#elif NETCORE
#endif
shimenum
namespace PortabilityLibrary.Shims
{
public class $enumname$Shim : Shim<
#if NETFULL
$enumname$
#elif NETCORE
string
#endif
>
{
public $enumname$Shim(string it)
#if NETFULL
: base(($enumname$)Enum.Parse(typeof($enumname$), it))
#elif NETCORE
: base(it)
#endif
{ }
}
}
shimsnip
namespace PortabilityLibrary.Shims
{
public class $classname$Shim : Shim<
#if NETFULL
$classname$
#elif NETCORE
$classname$
//NullObject
#endif
>
{
public $classname$Shim()
#if NETFULL
: base(new $classname$())
#elif NETCORE
: base(new $classname$())
//: base(new NullObject())
#endif
{}
}
}
shimmeth
public void $methodname$()
{
#if NETFULL
It.$methodname$();
#elif NETCORE
It.$methodname$();
//throw new ShimException();
#endif
}
shimprop - not yet
2) Case when inheritance needed.
public interface IShimOne
{
void MethodOne();
}
public interface IShimTwo: IShimOne
{
void MethodTwo();
}
#if NETFULL
class One: RealOne, IShimOne {}
class Two: RealTwo, IShimTwo {}
public static class ShimFactory
{
public static IShimOne CreateOne() { return new One(); }
public static IShimTwo CreateTwo() { return new Two(); }
}
2.a) Objects for inheritance
public class WrapperOne
{
protected IShimOne It { get; }
protected WrapperOne(IShimOne it) { It = it; }
public WrapperOne() { It = ShimFactory.CreateOne(); }
public void MethodOne() { It.MethodOne(); }
}
public class WrapperTwo: WrapperOne
{
protected new IShimTwo It => (IShimTwo)base.It;
protected WrapperTwo(IShimTwo it): base(it) {}
public WrapperTwo(): base(ShimFactory.CreateTwo()) {}
public void MethodTwo() { It.MethodTwo(); }
3) Ready "counterparts" for GUI controls (Eto.Forms)
(actually, Eto.Forms has wider application - they are the shims)
This framework can be used to build applications that run across multiple platforms using their native toolkit, with an easy to use API. This will make your applications look and work as a native application on all platforms, using a single UI codebase...
//Not fully implemented, just showing the idea:
#if NETFULL
using System.Windows.Controls;
#elif NETCORE
using Eto.Forms;
#endif
namespace PortabilityLibrary.Shims
{
public class MenuItemShim : Shim<
#if NETFULL
MenuItem
#elif NETCORE
MenuItem
#endif
>
{
public MenuItemShim(EventHandler<EventArgs> dlg)
#if NETFULL
: base(new MenuItem(/*not implemented*/))
#elif NETCORE
: base(new ButtonMenuItem(dlg))
#endif
{ }
}
}
I'm working on a c# windows desktop project using Entity Framework 6. There are 3 different project in the solution. Let's say ProjectA which is the startup project and includes the exe file; ProjectB which is the framework and includes the DbContext; and ProjectC which includes all the models.
Now I really don't know how I should enable migration for these different projects since each one is going to be a separate assembly.
I'm familiar with enable migration and add migration commands however I don't know how to use it when the context is in another assembly and the models in yet another assembly.
Please help.
Thanks in advance.
You can setup initialization classes that can be called from your startup project.
public static class InitializeAndSeed
{
public static void InitializeContext()
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<YourDbContext
,YourDbContextMigrations>());
using (var db = new YourDbContext())
{
db.Database.Initialize(false);
}
}
}
public class YourDbContextMigrations : DbMigrationsConfiguration<YourDbContext>
{
public YourDbContextMigrations ()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
//Your seeding and your migrations
}
Then, from your startup project you can call the InitializeContext() method to initialize the context from an application startup class or where ever you need. You just want to make sure you only initialize it once per application start.