Dapper: Cannot read/map Geometry type field in local SQL Server - sql-server

I am running ASP.NET Core 2 application.
I have a local instance of SQL Server where I have a table with a column of type Geometry.
When I go to read this table I get the following errors:
Type Udt is not supported on this platform.
Error parsing column 4 (MyLocation)
However this issue only seems to occur in my API project which calls to a custom made Nuget package that handles the CRUD operations.
If I test the same code in the project that does the CRUD it reads and maps my object.
It is not a connection issue in the API for I can successfully read/write other tables that do not have a Geometry field in it.
What could I possible be missing?
Code:
MyController:
public async Task<IActionResult> Get(Guid Id)
{
var rec = await myRepo.Get<MyData>(id);
// then do stuff
}
*myRepo is injected into my controller.
public class MyData
{
public Guid Id {get;set;}
public IGeometry MyLocation {get;set;}
}
myRepo:
public async Task<TEntity> Get<TEntity>(object id)
where TEntity : class
{
_conn.Open();
return await _conn.GetAsync<TEntity>(id);
}

If this is .NET Core, then I suspect you could have significant issues using sqlgeography etc; UDTs essentially aren't yet implemented in .NET Core:
Additionally, the underlying types that you would want to load use native code; the geo/etc types are not, AFAIK, available in .NET Core.
If I'm wrong, I'm more than happy to try to make whatever changes we need to help make this work, but at the time of writing: I don't think this is going to work through any API (it is not specific to Dapper).
You might want to consider using ASP.NET Core on .NET Framework for today? reference .Net framework 4.5.2 from .Net Core 2.0 project
If this data does actually load from ADO.NET in .NET Core, then I'd be happy to fix whatever I've missed.

Related

WPF Core DependencyInjection Scoped

I have the following projects:
.Net Standard 2.0 Service Lib
Asp.Net Web API Project
WPF Core 3.1 App
The plan was to share the Service layer between the API and the WPF App.
In the Web API I add a scoped UnitOfWork Service that itself uses scoped DbContexts
services.AddScoped<IUnitOfWork, UnitOfWork>();
The Service Layer uses the UnitOfWork for committing several queries across services (which are added scoped was well) in one transaction. This works as expected.
Service1:
public Service1(IService2 service2,IUnitOfWork unitOfWork)
{
...
}
public async DoSomething()
{
_unitOfWork.DBContext.SomeTable.Add(new SomeTableRecord())
_service2.AddSomeDbRecord(saveInstant:false); //adds a record in another table without saving
await _unitOfWork.SaveAllChanges(); //saves both db changes (inserts) in one transaction
}
Service 2:
public Service2(IUnitOfWork unitOfWork)
{
...
}
public async AddSomeDbRecord(bool saveInstant)
{
_unitOfWork.DBContext.SomeTable2.Add(new SomeTable2Record())
if(saveInstant)
await _unitOfWork.SaveAllChanges(); //saves both db changes (inserts) in one transaction
}
Now when adding my WPF Project where I don't have the Scope of a "WebRequest" anymore, what is a good way to define the scope. Ideally i would like the scope to be around the full chain of calls to a Services method.
I believe this would do what I wanted it to do:
using (var serviceScope = Host.Services.CreateScope())
{
var services = serviceScope.ServiceProvider;
var service1 = services.GetRequiredService<Service1>();
service1.DoSomething();
}
...but this is obviously not nice or straightforward to write for every call to the service lib and I cannot use ViewModel Constructor Injection for the services.
A scope per ViewModel Instance would be okay too I guess but I don't know how to do this (I'm using MVVM Pattern with a ViewModelLocator)
I would want to stay with Microsoft.Extensions.DependencyInjection as the DI framework as this is also what I'm using in the ASP.Net Project.

MongoDb + Silverlight - [BsonId] assignment

It seems like the official MongoDB C# driver is not supported in SilverLight. I want to use MongoDB on the server side and communicate the data via WCF to the silverlight client.
The problem is the Id property in my POCO - Since I can't import a non-silverlight project into the silverlight - I can't use [BsonId] or ObjectId in my POCO which should be used by both the server and the client.
I've seen questions here on SO about having the Id member as string, but represented as ObjectId in the DB, but I haven't seen solutions.
What's the best way to have
public string Id { get; set; }
in my class, but still enjoy the benefits of ObjectId on the server-side of things?
I've seen this page, I tried using SetIdMember and MapIdProperty, the _id was null on the inserted documents.
Checkout the documentation here for representation options: http://www.mongodb.org/display/DOCS/CSharp+Driver+Serialization+Tutorial#CSharpDriverSerializationTutorial-RepresentationSerializationOptions
Alternatively, you could use a Guid in both your code and in the database and not need to do mental translations when querying.

Consume SOAP Web Service in Silverlight

I'm attempting to consume a SOAP service in a Silverlight 5 application and I'm completely lost. This is my first Silverlight app and only my second time using web services in a .NET application.
In a separate .NET application, the only way I was able to get it to work was by adding the WSDL as a Web Reference; the application would not build when I added it as a Service Reference. In talking to the WSDL provider, I discovered that the WSDL was compiled using the .NET 2.0 framework...hence the need to add it as a Web Reference.
From the research I've done thus far, I see that Silverlight doesn't support adding a Web Reference. So I tried adding it to the hosting ASP.NET application as a Web Reference then started the server.
Back in my Silverlight app, I selected the option to add a Service Reference and pointed to the WSDL file now at http://localhost:55265/Web%20References/THINKWebService/SLWebSvc_734_Upgrade.wsdl. Visual Studio seemed to pick it up just fine and generate the proxies.
Here's where I start to get stuck. If my research is correct, a WCF reference was created and should be used in that manner. I've never used WCF so I did some reading on how to send/receive requests and this is the best code I've come up with, based on examples in the MSDN library (I inserted it into a button click event so I would know exactly when the code was executing):
private void Button1Click(object sender, RoutedEventArgs e)
{
var client = new ThinkSoapClient();
var userLoginData = new user_login_data {login = "foo", password = "bar"};
var customerIdentifier = new customer_identifier {customer_id = 6677070};
// the debugger halts on this next line and
// references the "dsn"...it's the 4th argument
client.CustomerLoginInfoSelectAsync(userLoginData, customerIdentifier, "", "myDSN");
// I'm not sure if this next line is even needed
client.CustomerLoginInfoSelectCompleted += CustomerLoginInfoSelectCallback;
MessageBox.Show(string.Format("CustomerLoginInfoSelectAsync({0},{1})", userLoginData, customerIdentifier));
}
// here's the callback method
static void CustomerLoginInfoSelectCallback(object sender, CustomerLoginInfoSelectCompletedEventArgs e)
{
MessageBox.Show(string.Format("CustomerLoginInfoSelect Result: {0}", e.Result));
}
As I mentioned in the code above, the debugger halts when executing the client.CustomerLoginInfoSelectAsync method. Here's the error message: XmlSerializer attribute System.Xml.Serialization.XmlAttributeAttribute is not valid in dsn. Only XmlElement, XmlArray, XmlArrayItem and XmlAnyElement attributes are supported when IsWrapped is true.
From the research I've done, I think this error is being caused because the the SOAP action element contains an attribute dsn (not sure, though, if I would be getting this error if the sub-elements also had attributes).
I did a find/replace for IsWrapped=true to IsWrapped=false in Reference.cs but I got the same error but the last word was false instead of true.
I'm not sure if I'm making any sense as to what I'm after, so here's what the generated XML should look like in case it helps:
...
<customer_login_info_select_request dsn="myDSN">
<user_login_data>
<login>foo</login>
<password>bar</password>
</user_login_data>
<customer_identifier>
<customer_id>6677070</customer_id>
</customer_identifier>
<login/> <!--corresponds to the empty string in the call to CustomerLoginInfoSelectAsync-->
</customer_login_info_select_request>
...
So at this point, I'm completely lost. Any insights would be greatly appreciated. If there's any other info I can provide, please let me know.
While possible the normal solution would be to assume it is "just another data source" and use the Web reference on your Server side instead to provide data (and to provide insulation against future changes).
Silverlight App <=> Silverlight Web Services <= External/Legacy Web Service
Keep your Silverlight app slim and let the server do any heavy lifting for you.

Task-Based data service in Silverlight

I'm trying to write a silverlight app using the await/async 'pattern' (using SL5 and VS11), but I cannot select the 'Generate Task-Based operations' in the service config, is this supposed to be possible (yet)? Can't find much detail on the web (specific to SL)...
I have been able to create manually Task based asynchronous service proxy in Silverlight 5 and Visual Studio 2010.
Works like charm.
I personally prefer to code my contracts and service proxies manually, but if you like to use Generate Service reference you can take a look at this post - WCF + Tasks.
I think it is not supported in Silverlight but you can do that yourself, Maybe a portable class library would be another workaround for this.
public class MyCServiceProxy
{
public static Task<ObservableCollection<MyC>> GetMyCs()
{
var tcs = new TaskCompletionSource<ObservableCollection<MyC>>();
var client = new MyCServiceClient();
client.GetMyCsCompleted += (s,e) => {};
client.GetMyCsAsync();
return tcs.Task;
}
}

WCF data insertion fails

I have a Silverlight application that connects to a remote server. I am using EF + WCF for database connection. I can retrieve data with no problem, but if I want to insert a new entry to the table, I get the following exception:
[HttpWebRequest_WebException_RemoteServer]
Arguments: NotFound
And then there is a lot of stack trace information that is not directly related to my code. Here is how the WCF service adds a new entry:
[OperationContract]
public void addNewEntry(INFORMATION info)
{
myDBEntities en = new myDBEntities();
en.AddToINFORMATION(info);
en.SaveChanges();
}
I pass an INFORMATION object from the client to the service which attempts to save the new entry to the table. The object itself is properly constructed.
What am I doing wrong? I don't understand why I can retrieve data but not save any.
It could be several things:
You are in the security context of a user that is allowed to get data, but not save data
There is a required field in the table that you are not sending in
Along with the other comments, why do you have your database logic in the [OperationContract] method.
You should abstract the business / database logic into different classes / assemblies...food for thought.

Resources