Can't set up entity framework core - entity-framework

I'm trying to set up a db context in a .net core F# web app. As part of this I need to convert the following in to F#:
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
My F# version is:
services.AddDbContext<ApplicationDbContext>(fun (options: DbContextOptionsBuilder) ->
options.UseSqlite(this.Configuration.GetConnectionString("DefaultConnection")))
However, I am getting the following exception:
No overloads match for method 'AddDbContext'. The available overloads are shown below (or in the Error List window).property Startup.Configuration: IConfigurationRoot
What could the problem be?

The problem was that I hadn't added a constructor for ApplicationDbContext that takes a DbContextOptions as a parameter. After changing the default constructor to
type ApplicationDbContext(options: DbContextOptions<ApplicationDbContext>) =
inherit IdentityDbContext<ApplicationUser>(options)
I could compile

UseSqlite return Microsoft.EntityFrameworkCore.DbContextOptionsBuilder value, so you need ignore it to match Action<DbContextOptionsBuilder>.
services.AddDbContext<ApplicationDbContext>(fun (options: DbContextOptionsBuilder) ->
options.UseSqlite(this.Configuration.GetConnectionString("DefaultConnection")) |> ignore)

Related

C# Entity Framework : include with string parameter versus include with lambda expression [duplicate]

I am using entity framework and I want to execute a query and would like to know which is the besr way to execute a query. Which is best practice and why, and which one is more per-formant.
Option 1)
return
this.Storage.Customer.OfType<Preferred>()
.Include("Order")
.Where("it.Id = #customerId AND it.CustomerType = #cusType", new ObjectParameter("customerId ", customerId), new ObjectParameter("cusType", (int)cusType))
.Execute(MergeOption.OverwriteChanges)
.SingleOrDefault();
OR
return
this.Storage.Customer.OfType<Preferred>()
.Include(b => b.Order)
.Where(cust => cust.Id == customerId && cust.CustomerType== (int)cusType)
.SingleOrDefault();
The second question is why in option 2 us the .Execute not available? It appears red.
Thanks in advance.
The performance difference should be negligible compared with the actual data access, but you need to measure it to determine for sure.
Include with a lambda just uses reflection to get the property name then calls the version with a string parameter, so the only overhead is parsing the expression. (This is an implementation detail, however, so it is subject to change)
The benefit of using a lambda is type safety - using the wrong property name in a lambda will break the build, but using the wrong string will only fail at run-time.
The reason Execute is not available is because Include with a lambda parameter is an extension method on IQueryable<T> that returns an IQueryable<T> in order to chain methods like Where. Include with a string parameter is a method on ObjectQuery<T> that returns an ObjectQuery<T>. Execute is a method on ObjectQuery<T>, not IQueryable<T> so it is not available when you use IQueryable methods.

EF Core: Automaticall Save Enums as Strings Without Calling HasConversion For Every Single Property

Using EF Core I can tell the modelBuilder to save properties having of enum type as string:
modelBuilder
.Entity<MyEntity>()
.Property(e => e.SomeEnumProperty)
.HasConversion<string>();
This has been asked and answered several times and is also described in the official docs.
However, the list of entitiy types (modelBuilder.Model.GetEntityTypes()) and their subtypes used in my project is rather lengthy and I image it to be error prone to loop over all managed entities, get their properties and their children properties recursivly via reflection and kind of semi-manually add the string conversion.
Is there a builtin way to automatically save all enum property values as strings using the StringEnumConverter?
Currently (EF Core 3.1.7) there is no other way than the one described in EF CORE 2.1 HasConversion on all properties of type datetime.
The difference here is the way of identifying Enum type properties, and due to the lack of easy public way of getting entity type builder (this property builder), the direct usage of SetProviderClrType metadata API instead of more intuitive HasConversion:
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
foreach (var property in entityType.GetProperties())
{
var propertyType = Nullable.GetUnderlyingType(property.ClrType) ?? property.ClrType;
if (propertyType.IsEnum)
property.SetProviderClrType(typeof(string));
}
}
This must be at the end of your OnModelCreating override, or more specifically, after all entity types have been discovered.

The type 'FluentValidation.IValidator' is not an open generic class

On an ASP.NET Core application I am registering
services.Scan(x => x.FromAssembliesOf(typeof(Startup))
.AddClasses(y => y.AssignableTo(typeof(IValidator)))
.AsImplementedInterfaces()
.WithScopedLifetime());
I tried to replicate this using Autofac so I used:
builder
.RegisterAssemblyTypes(typeof(Startup).Assembly)
.AsClosedTypesOf(typeof(IValidator))
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
But I got the following error:
Unhandled Exception: System.ArgumentException:
The type 'FluentValidation.IValidator' is not an open generic class or interface type so it won't work with methods that act on open generics.
What am I doing wrong?
Instead of AsClosedTypesOf use a Where clause to filter out and register just the types that implement IValidator. AsClosedTypesOf is specifically there to support open generics. There are plenty of examples in the Autofac docs to help you out.

Update entity from expression (EF Core 2.0)

How can I update entity from expression?
I dynamically build which properties(columns) should be updated. Function that do that returns Expression<Func<T, T>> where T is entity.
I have loaded entity from database using Where and Single.
Expression<Func<T, T>> expr = this.CallVirtualMethodAndGetExpression(ModelFromRequest);
DbUser entity = this.context.Users.Where(t => t.Id == 1).Single();
some magic ??? //tried expr.Compile()(entity) but it does not work.
this.context.SaveChanges();
//use DbUser with updated properties of course.
I know I could use EF Plus (batch update), but I want to stick with SaveChanges (I need DbUser after SaveChanges and I want to avoid sending another request).
Updated:
I have entity object and expression. Now, I need to edit entity object based on expression and called SaveChanges which should update entity.
the magic line you are looking for:
var resultOfTypeT = expr.Compile().Invoke(entity)
But then entity needs to be an instance of type T , not DbUser
So this does not make sense to me.
So i cant give you exact code to compile for you, since i cant see the method signature where T is defined. and also do not know what the method signature of this.CallVirtualMethodAndGetExpression(ModelFromRequest) looks like.
But the Compile() will change the Expression<Func<T,T>> to just Func<T,T> which can then Invoke the defined functionality for Func<T,T> if you have a valid instance of T to pass to it.
Now your entity is not of type T, since it is of type DbUser So you are probably going to need to change your Method Signature or get your DbUser in a generic way or something. If you are only going to need to pass a DbUser instance, you do not need c# Generics. but cant really tell with just the current information available.

Registering Collections in Autofac 2.1.10 RC

I am upgrading code from Autofac 1.4 to 2.1.10 Release Candidate.
My module previously performed registration like this:
builder.RegisterCollection<IExceptionHandler>()
.As<IEnumerable<IExceptionHandler>>()
.FactoryScoped();
builder.Register<AspNetExceptionHandler>()
.As<IExceptionHandler>()
.MemberOf<IEnumerable<IExceptionHandler>>()
.FactoryScoped();
Now, RegisterCollection has no parameterless overload. I don't care about assigning it a name. Assuming it's OK to just pass in null, my code looks like this in 2.1:
builder.RegisterCollection<IExceptionHandler>(null)
.As<IEnumerable<IExceptionHandler>>()
.InstancePerDependency();
builder.RegisterType<AspNetExceptionHandler>()
.As<IExceptionHandler>()
.MemberOf<IEnumerable<IExceptionHandler>>(null)
.InstancePerDependency();
However, when I compile, I get the following error regarding .MemberOf:
Using the generic method
'Autofac.RegistrationExtensions.MemberOf(Autofac.Builder.RegistrationBuilder,
string)' requires '3' type arguments
I tried putting in a collection name instead of null, just in case, and that had no effect.
What's the proper way to register collections in 2.1?
As I understand it, you just register a bunch of IExceptionHandler types, and then when you request an IEnumerable<IExceptionHandler> Autofac 2 will just take care of everything for you.
From the NewInV2 page:
builder.RegisterType<A1>().As<IA>();
builder.RegisterType<A2>().As<IA>();
var container = builder.Build();
// Contains an instance of both A1 and A2
Assert.AreEqual(2, container.Resolve<IEnumerable<IA>>().Count());