I'm working on a simple import tool written in C# for .NET Framework 4.7 to read a MS-Access file and save it to a PostGIS database.
I'm having trouble letting EF6 now my Point
object is a NetTopology class and not another table.
When I read of write my data from my PostGIS database I get this error:
System.Data.Entity.ModelConfiguration.ModelValidationException
HResult=0x80131500
Message=One or more validation errors were detected during model generation:
Importer.Point: : EntityType 'Point' has no key defined. Define the key for this EntityType.
Points: EntityType: EntitySet 'Points' is based on type 'Point' that has no keys defined.
Here is some code:
public static void Main(string[] args)
{
// Place this at the beginning of your program to use NetTopologySuite everywhere (recommended)
NpgsqlConnection.GlobalTypeMapper.UseNetTopologySuite();
using (var context = new PostGisContext())
{
var newKey = context.MyLocations.Count();
}
}
context.MyLocations.Count()
is throwing the error.
public class PostGisContext : DbContext
{
public DbSet<MyLocation> MyLocations { get; set; }
public PostGisContext() : base("name=PostgreSql")
{ }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// PostgreSQL uses the data schema by default - not dbo.
modelBuilder.HasDefaultSchema("data");
// Don't use plural table names:
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
// Change CamelCase to lower-case:
modelBuilder.Types().Configure(c => c.ToTable(LowerCaseTableName(c.ClrType)));
modelBuilder.Conventions.Add(new LowerCaseConvention());
base.OnModelCreating(modelBuilder);
}
private static string LowerCaseTableName(Type type)
{
var result = Regex.Replace(type.Name, ".[A-Z]", m => m.Value[0] + "_" + m.Value[1]);
return result.ToLower();
}
}
// A custom convention.
internal class LowerCaseConvention : IStoreModelConvention<EdmProperty>
{
public void Apply(EdmProperty property, DbModel model)
{
property.Name = Regex.Replace(property.Name, ".[A-Z]", m => m.Value[0] + "_" + m.Value[1]).ToLower();
}
}
When changing the Location
column to string the above code works fine.
public class MyLocation
{
[Key]
public int Id { get; set; }
public string LocationId { get; set; }
public NetTopologySuite.Geometries.Point Location { get; set; }
}
public class NpgSqlConfiguration : DbConfiguration
{
public NpgSqlConfiguration()
{
const string name = "Npgsql";
SetProviderFactory(providerInvariantName: name,
providerFactory: NpgsqlFactory.Instance);
SetProviderServices(providerInvariantName: name,
provider: NpgsqlServices.Instance);
SetDefaultConnectionFactory(connectionFactory: new NpgsqlConnectionFactory());
}
}
I must be forgetting a setting or something, but I can't find it. Any help will be much appreciated.
NetTopologySuite and PostGIS aren't supported in Entity Framework 6, only in Entity Framework Core. This is because EF6's type system is closed and does not allow for flexible provider-specific extensions in the way that EF Core does.