Entity Framework Core - EF Core 2.2 - 'Point.Boundary' is of an interface type ('IGeometry') - entity-framework-core-2.1

I am trying the new functionality with EF Core 2.2. It is based on the following article. "Announcing Entity Framework Core 2.2"
https://blogs.msdn.microsoft.com/dotnet/2018/12/04/announcing-entity-framework-core-2-2/
I installed the following Nuget package.
I added the following to my model.
using NetTopologySuite.Geometries;
//New as of EF.Core 2.2
//[Required]
//[NotMapped]
public Point Location { get; set; }
During my application startup I get the following error in my Database Context on the following line:
Database.EnsureCreated();
System.InvalidOperationException
HResult=0x80131509
Message=The property 'Point.Boundary' is of an interface type ('IGeometry'). If it is a navigation property manually configure the relationship for this property by casting it to a mapped entity type, otherwise ignore the property using the NotMappedAttribute or 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.
Source=Microsoft.EntityFrameworkCore

You need to call UseNetTopologySuite(). Example here:
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var connectionString = configuration.GetConnectionString("DefaultConnection");
optionsBuilder.UseSqlServer(connectionString, opts => opts.UseNetTopologySuite());
}
public DbSet<Test> Tests { get; set; }
}
public class Test
{
public int Id { get; set; }
public Point Location { get; set; }
}
I ran into this problem because I had a
if (!optionsBuilder.IsConfigured) around everything in my OnConfiguring. I had to remove this in order to get add-migrations to work.

As Kyle pointed out you need to call UseNetTopologySuite(), but I would call it during ConfigureServices like this:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services
.AddEntityFrameworkNpgsql()
.AddDbContext<MyDBContext>(opt =>
opt.UseNpgsql(Configuration.GetConnectionString("MyDBConnection"),
o=>o.UseNetTopologySuite()))
.BuildServiceProvider();
...
}
...
}

Related

Can't cast database type character to Guid

I updated my solution from .Net 3.1 to .Net 6. Also updated the Npgsql nuget package from 5.0.10 to 6.0.4 as part of this upgrade.
Since then, I am receiving an error "Can't cast database type character to Guid" when I try to retreive data from the database.
My mapping in the context file is
entity.Property(e => e.UserId).HasColumnName("user_id").HasColumnType("CHAR(36)");
In C# class, this property is a GUID.
Is there some mapping update with the newer version of npgsql?
EF Core has a built-in value converter which implicitly converts .NET Guid properties to text columns (see docs. Note that PostgreSQL has a full UUID type - that's a better way to store GUIDs in the database, rather than as text.
This works in EF Core 6.0.4 - if you're encountering trouble, please produce a minimal, runnable code sample and add it to your question above.
Working 6.0 code:
await using var ctx = new BlogContext();
await ctx.Database.EnsureDeletedAsync();
await ctx.Database.EnsureCreatedAsync();
ctx.Blogs.Add(new Blog { Guid = Guid.NewGuid()});
await ctx.SaveChangesAsync();
_ = await ctx.Blogs.ToListAsync();
public class BlogContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseNpgsql(#"Host=localhost;Username=test;Password=test")
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();
}
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
[Column(TypeName = "CHAR(36)")]
public Guid Guid { get; set; }
}

AspnetBoilerplate modular: The entity type XXX is not part of the model for the current context

Sorry for my bad English, Could anyone help me with this error as below:
I have followed this tutorial to create a new module application (named Payment) on AspnetZero framework (named FastOne).
In the second DbContext, I change the default conn to my second database and add new entity name BankCode. After add-migration and update-database, everything works well. New database was created with 1 table name BankCode
I went to create a AppService in .Application module project as below:
public class BankCodeAppService : FastOneAppServiceBase, IBankCodeAppService
{
//from PaymentDbContext
private readonly IRepository<BankCode> _repository;
public BankCodeAppService(IRepository<BankCode> repository)
{
_repository = repository;
}
public ListResultDto<BankCodeDto> GetAllBankCodeDto()
{
try
{
var result = _repository.GetAll().ToList();
return new ListResultDto<BankCodeDto>(result.MapTo<List<BankCodeDto>>());
}
catch (Exception ex)
{
throw new NotImplementedException();
}
}
}
This is my PaymentDbContext
[DefaultDbContext]
[AutoRepositoryTypes(
typeof(IPaymentRepositoryBase<>),
typeof(IPaymentRepositoryBase<,>),
typeof(PaymentRepositoryBase<>),
typeof(PaymentRepositoryBase<,>)
)]
public class PaymentDbContext : FastOneDbContext
{
/* Define an IDbSet for each entity of the application */
public virtual IDbSet<BankCode.BankCode> BankCodes { get; set; }
//TODO: Define an IDbSet for your Entities...
public PaymentDbContext() : base("SecondConn") { }
public PaymentDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { }
public PaymentDbContext(DbConnection connection) : base(connection) { }
}
The api was created successfully, but when I called to it, it returned the error as below:
The entity type BankCode is not part of the model for the current
context.
I tried to debug and realize that the repository is FastOneDbContext instead of PaymentDbContext : [Wrong repository when debugging][2]
I'm totally new with AspNetBoilerplate and module Zero. So could anyone please to help me. Thank
Update: This is my PaymentRepositoryBase
namespace FastOne.EntityFramework.Repositories
{
public class PaymentRepositoryBase<TEntity, TPrimaryKey> : FastOneRepositoryBase<TEntity, TPrimaryKey>
where TEntity : class, IEntity<TPrimaryKey>
{
public PaymentRepositoryBase(IDbContextProvider<PaymentDbContext> dbContextProvider) : base(dbContextProvider) { }
//do not add any method here, add to the class above (since this inherits it)
}
public abstract class PaymentRepositoryBase<TEntity> : PaymentRepositoryBase<TEntity, int>
where TEntity : class, IEntity<int>
{
public PaymentRepositoryBase(IDbContextProvider<PaymentDbContext> dbContextProvider) : base(dbContextProvider) { }
//do not add any method here, add to the class above (since this inherits it)
}
}
Update 3
Thank for your help Aaron, everything goes correctly, this is the newest error, I have searched some solutions but they didn't work. Please help
No component for supporting the service
FastOne.EntityFramework.PaymentDbContext was found
Update 4
I tried to add this method to PaymentDataModule:
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
It worked!, I can see _repository get correct context. but when i run, it raised this error:
System.Data.SqlClient.SqlException: Invalid object name
'dbo.BankCode'.
I realized that the connection was wrong. It was the connstring of the first context
Update 5: I found that I have 3 constructors in PaymentDbContext. So i removed these lines:
public PaymentDbContext() : base("LocalPaymentConn") { }
//public PaymentDbContext(string nameOrConnectionString) : base(nameOrConnectionString) { }
//public PaymentDbContext(DbConnection connection) : base(connection) { }
-->It received the correct connection string. So awesome!! Thanks Aaron and Tien for all your help. Thank you
You should inject IPaymentRepositoryBase as you have specified in AutoRepositoryTypes.
public class BankCodeAppService : FastOneAppServiceBase, IBankCodeAppService
{
private readonly IPaymentRepositoryBase<BankCode> _repository;
public BankCodeAppService(IPaymentRepositoryBase<BankCode> repository)
{
_repository = repository;
}
}
Update 1
ComponentActivator: could not instantiate FastOne.EntityFramework.Repositories.PaymentRepositoryBase`1‌​[[FastOne.BankCode.B‌​ankCode, FastOne.Payment.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]
Remove abstract keyword from the class declaration for PaymentRepositoryBase<TEntity>.
Update 2
Target does not implement interface FastOne.Domain.Repositories.IPaymentRepositoryBase`1[[FastOn‌​e.BankCode.BankCode, FastOne.Payment.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]\r\nParameter name: target
Make PaymentRepositoryBase implement IPaymentRepositoryBase.
public class PaymentRepositoryBase<TEntity> : PaymentRepositoryBase<TEntity, int>, IPaymentRepositoryBase<TEntity>
where TEntity : class, IEntity<int>
{
public PaymentRepositoryBase(IDbContextProvider<PaymentDbContext> dbContextProvider) : base(dbContextProvider) { }
}
You are using mutilple dbcontext in the app. So the second context must be inherit from AbpDbContext to ABP inject this correctly. See MultipleDbContextDemo example on https://github.com/aspnetboilerplate/aspnetboilerplate-samples.
Hope this will help you.

Using Automapper to map object to realm object with Xamarin and c#

I am creating an Xamarin.iOS app and a Realm database.I would like to keep my POCO objects separate from my RealmObject so what I did was use a repository pattern and within the repository I tried to use AutoMapper to map the POCO to the RealmObject
e.g. (subset)
public class PlaceRepository : IPlaceRepository
{
private Realm _realm;
public PlaceRepository(RealmConfiguration config)
{
_realm = Realm.GetInstance(config);
}
public void Add(Place place)
{
using (var trans = _realm.BeginWrite())
{
var placeRealm = _realm.CreateObject<PlaceRealm>();
placeRealm = Mapper.Map<Place, PlaceRealm>(place);
trans.Commit();
}
}
So, if I debug my code everything maps OK and placeRealm is populated OK but when I commit nothing gets saved to the Realm db. The following is my RealmObject
public class PlaceRealm : RealmObject
{
[ObjectId]
public string Guid { get; set; }
public string Title { get; set; }
public string Notes { get; set; }
}
and this is my POCO Place
public class Place
{
public string Guid { get; set; }
public string Title { get; set; }
public string Notes { get; set; }
}
And AutoMapper is initialized like so:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Place, PlaceRealm>();
cfg.CreateMap<PlaceRealm, Place>();
});
All standard stuff. Has anyone else managed to get something similar working?
Your poco 'Place' is called 'PlaceRealm'. I suspect that is a typo. (made edit)
I suspect that Automapper is instantiating a new object overwriting your original 'placeRealm' object.
Perhaps you could try
Mapper.Map(place, placeRealm);
in place of your current mapping.
which should just copy the values to your already instatiated and tracked object.
(no need to store the return value).
You might also want to make explicit which properties (3) you are mapping as currently Automapper will map all including those in the base class.
On a side note, you may run into performance issues with Automapper. I found it to be the performance bottleneck in some apps. ExpressMapper is a nice alternative.

Configure AutoMapper to return Mock in test layer

In my app, all domain classes follow the standardization:
All implement the interface IEntity
Id properties are protected*
The properties of type IList are protected and initialized in the constructor.
Below is a classic example of a domain entity:
public class CheckListItemTemplate : IEntity
{
public virtual int Id { get; protected set; }
public virtual string Text { get; set; }
public virtual CheckListItemTemplate Parent { get; set; }
public virtual IList<CheckListItemTemplate> Itens { get; protected set; }
public CheckListItemTemplate()
{
Itens = new List<CheckListItemTemplate>();
}
public void AddItem(CheckListItemTemplate item)
{
item.Parent = this;
Itens.Add(item);
}
}
*This is because the id is generated by the database and not run the risk of some developer trying to set this property.
Test project
We have a fake generic repository used in the tests:
public class Repository<T> : IRepository<T>
where T : class, IEntity
{
private readonly IDictionary<int, T> _context = new Dictionary<int, T>();
public void Delete(T obj)
{
_context.Remove(obj.Id);
}
public void Store(T obj)
{
if (obj.Id > 0)
_context[obj.Id] = obj;
else
{
var generateId = _context.Values.Any() ? _context.Values.Max(p => p.Id) + 1 : 1;
var stub = Mock.Get<T>(obj);
stub.Setup(s => s.Id).Returns(generateId);
_context.Add(generateId, stub.Object);
}
}
// ..
}
As you can see in the Store*, all test objects (of type IEntity) should be a Mock**. This is because in UI project, when we save an object NHibernate updating the property Id. In testing project we have to do this manually, and we have no way to set the property Id with a new value, so the solution was mock the entire object to the Get property Id correspond to the new Id . Exactly what does this line stub.Setup(s => s.Id).Returns(generateId).
*By convention, objects with Id <= 0 are new and Id> 0 are existing objects in the database.
**For Mock I use Moq.
Id as protected
The biggest problem occurs because of Id property and the fact that is protected.
When we talk about the designer, is a great approach but this brings huge inconvenience when we test our application.
For example, in a test that I'm writing I need my Fake repository with some data already populated.
Code
Follow me. I have the following classes (+ CheckListItemTemplate shown above.)
public class Passo : IEntity
{
public int Id { get; protected set; }
public virtual IList<CheckListItemTemplate> CheckListItens { get; protected set; }
}
public class Processo : IEntity
{
public virtual int Id { get; protected set; }
public virtual Passo Passo { get; set; }
public virtual IList<CheckListItem> CheckListItens { get; protected set; }
}
After saving the Processo, the first Passo is associated with the Processo: (sorted by Ordem field following field CreateAt)
model.Passo = PassoRepositorio.All().OrderBy(p => p.Ordem).ThenBy(p => p.CreateAt).First();
model.CheckListItens.Clear();
Parallel.ForEach(Mapper.Map<IList<CheckListItem>>(model.Passo.CheckListItens), (it) => model.AddCheckListItem(it));
This code is running whenever you save a new Processo. For any test that creates a new Processo, this code will be executed!
Test
If we have to create a test that creates a new Processo, our first goal is to populate the PassoRepositorio repository with some dummy data*, with Passos and CheckListItemTemplates specifically for the above code does not fail**.
*To populate objects with dummy data I use AutoFixture.
** Will fail if no Passo is found in the repository .First() and this Passo has no checklist Mapper.Map(model.Passo.CheckListItens).
So we need a repository of Passos and each Passo with a list of CheckListItens.
Remember that every object IEntity should be an Mock<> so we can mock property Id
First attempt
First configure my TestInitialize to populate my repository with some dummy data:
var fix = new Fixture();
var listPassos = fix.Build<Mock<Passo>>()
.Do((passo) => {
passo.SetupProperty(x => x.Nome, fix.Create<string>());
passo.SetupGet(x => x.CheckListItens).Returns(
fix.Build<CheckListItemTemplate>() // Needs to a Mock<>
.With(p => p.Texto)
.OmitAutoProperties()
.CreateMany(5).ToList()
);
})
.OmitAutoProperties()
.CreateMany(10);
foreach (var item in listPassos)
passoRepository.Store(item.Object);
Then I can run the tests:
[TestMethod]
public void Salvar_novo_processo_modificar_data_atendimento_passo_atual()
{
// Arrange
var fix = new Fixture();
var vm = fix.Create<ProcessoViewModel>();
//Act
Controller.salvar(vm); // Problem here. (For convert ProcessoViewModel to Processo I use a AutoMaper. In repository needs destination to be a Mock<Processo>
var processo = Repository.Get(p => p.DataEntrada == vm.DataEntrada && p.ProximoAtendimento == vm.ProximoAtendimento);
//Asserts
processo.Should().NotBeNull();
processo.Passo.Should().NotBeNull();
}
Questions
We create a list of 10 Passo where each Passo is actually is a Mock<>, great! But:
For each Passo have a list of 5 'Mock' items, and each Id should be 1, 2, 3, 4 and 5 (in that order). How to achieve this? How to obtain this list of IList<Mock<>> inside a Mock<> with Id already filled? That is, the configuration
passo.SetupGet(x => x.CheckListItens).Returns( ???
The responsible for creating objects in my controller, basically uses AutoMapper to convert my ViewModel object to an object that can be persisted Model in my repository:
model = Mapper.Map<TModel>(vm);
The problem is that my repository Fake can not save an object IEntity, just Mock<IEntity>. How to configure AutoMapper to always return a Mock<>?
Answer for Question 1: In case this helps, you can use a closure to maintain a running counter to use as an id. For example:
class MyTestClass
{
int _runningCounter = 0;
public void SomeTest()
{
/* ... some other code including mock creation ...*/
someMock.Setup(m => m.ReturnNewWidgetEntity())
.Returns(() => new WidgetEntity{ Id= ++_runningCounter });
}
}
Each time ReturnNewWidgetEntity is called on the mocked object, the Id property will be set to an increased number.
Answer for Question 2: I would suggest that rather than having a concrete dependency on the Mapper class, you replace this with an injected dependency on IMapperEngine. Richard Dingwall explains the technique here: http://richarddingwall.name/2009/05/07/mocking-out-automapper-with-dependency-injection/
Basically you register Mapper.Engine as the singleton implementation of IMapperEngine in your container and then in your unit tests mock it so that it gives you the required Mock<> classes.
I hope one or both of these answers at least give you food for thought. It was a bit difficult to follow your whole example, to be honest!

Nested Server Controls

I've got a server control that contains nested server controls,
<uc1:ArticleControl runat="server">
<HeadLine></HeadLine>
<Blurb></Blurb>
<Body></Body>
</uc1:ArticleControl>
Code:
[ToolboxData("<{0}:ArticleControl runat=server></{0}:ArticleControl>")]
[ParseChildren(ChildrenAsProperties = true)]
public class ArticleControl : WebControl
{
[PersistenceMode(PersistenceMode.InnerProperty)]
public HeadLineControl HeadLine
{
get;
set;
}
[PersistenceMode(PersistenceMode.InnerProperty)]
public BlurbControl Blurb
{
get;
set;
}
[PersistenceMode(PersistenceMode.InnerProperty)]
public BodyControl Body
{
get;
set;
}
}
Nested control definition (applies to all nested controls):
public class HeadLineControl : ControlBase
{
public HeadLineControl() : base() { }
public HeadLineControl(Article article) : base(article) { }
Base class definition
public abstract class ControlBase : Control
{
protected Article article;
protected ControlBase() { }
protected ControlBase(Article article)
{
this.article = article;
}
The ArticleControl is responsible for writing for the individual parts of the article specified by the nested controls,
My problem is that when the Articlecontrol is created, instances of the nested server controls are created by the .NET framework using the default constructor defined for the System.Web.Ui.Control class eg:
namespace System.Web.UI
{
public class Control : IComponent, IDisposable, IParserAccessor, IUrlResolutionService, IDataBindingsAccessor, IControlBuilderAccessor, IControlDesignerAccessor, IExpressionsAccessor
{
// Summary:
// Initializes a new instance of the System.Web.UI.Control class.
public Control();
I need to call or override the default behaviour of .Net to call my Control base class constructor in stead of the default .Net defined contructor. So in short, if a new instance of HeadLineControl is created, it needs to created by the ControlBase(Article article) constuctor.
Is this possible and if possible, how do I accomplish this?
I've done this in the meanwhile as a workaround, but there must be a better way?
[PersistenceMode(PersistenceMode.InnerProperty)]
public HeadLineControl HeadLine
{
get { return null; }
set
{
this.Controls.Add(new HeadLineControl(articlePage.Article)();
}
}

Resources