C# Azure MongoDB Linq Near Query - c#

I'm trying to send a query with a location point to Azure Cosmos DB (MongoDB) and get the locations near that point.
I got most of the information from here. And I'm using Microsoft.Azure.Documents.Spatial;.
So far, I've tried many solutions of other older posts, and nothing has worked for me.
My class definition:
public class Place : INotifyPropertyChanged
{
[BsonId(IdGenerator = typeof(CombGuidGenerator))]
public Guid Id { get; set; }
Point _location;
[BsonElement("Location")]
public Point Location
{
get => _location;
set
{
if (_location == value)
return;
_location = value;
HandlePropertyChanged();
}
}
long _addedDate;
[BsonElement("AddedDate")]
public long AddedDate
{
get => _addedDate;
set
{
if (_addedDate == value)
return;
_addedDate = value;
HandlePropertyChanged();
}
}
void HandlePropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
Mongo connection:
// APIKeys.Connection string is found in the portal under the "Connection String" blade
MongoClientSettings settings = MongoClientSettings.FromUrl(
new MongoUrl(APIKeys.ConnectionString)
);
settings.SslSettings =
new SslSettings() { EnabledSslProtocols = SslProtocols.Tls12 };
// Initialize the client
var mongoClient = new MongoClient(settings);
// This will create or get the database
var db = mongoClient.GetDatabase(dbName);
// This will create or get the collection
var collectionSettings = new MongoCollectionSettings { ReadPreference = ReadPreference.Nearest };
PlacesCollection = db.GetCollection<Place>(collectionName, collectionSettings);
Query:
var point = new Point(22, -5);
IMongoQueryable<Place> query = PlacesCollection.AsQueryable().Where(p => p.Location.Distance(point) < 30000);
return query.ToList();
I get the following error in return query.ToList():
Unhandled Exception:
System.InvalidOperationException:
{document}{Location}.Distance(value(Microsoft.Azure.Documents.Spatial.Point))
is not supported.
I don't understand what is not supported neither how to create the correct query for this. Any idea?
Edit:
Call Stack
0xE0 in XamFormsMaps.Core.Services.MongoService.GetPlacesNear at C:\Users\Role\source\repos\XamFormsMaps\XamFormsMaps\XamFormsMaps.Core\Services\MongoService.cs:84,13 C#
[External Code]
0x20 in XamFormsMaps.Core.Services.DatabaseService.GetPlacesNear at C:\Users\Role\source\repos\XamFormsMaps\XamFormsMaps\XamFormsMaps.Core\Services\DatabaseService.cs:20,13 C#
0x7A in XamFormsMaps.Core.ViewModels.MapViewModel.GetPlacesAsync at C:\Users\Role\source\repos\XamFormsMaps\XamFormsMaps\XamFormsMaps.Core\ViewModels\MapViewModel.cs:112,17 C#
0x6D in XamFormsMaps.Core.Pages.MapPage.<-ctor<-ctor>b__0_1>d at C:\Users\Role\source\repos\XamFormsMaps\XamFormsMaps\XamFormsMaps.Core\Pages\MapPage.xaml.cs:27,17 C#

Solved.
First, I had to change the Location type in the model to:
GeoJsonPoint<GeoJson2DGeographicCoordinates> _location;
[BsonElement("Location")]
public GeoJsonPoint<GeoJson2DGeographicCoordinates> Location
{
get => _location;
set
{
if (_location == value)
return;
_location = value;
HandlePropertyChanged();
}
}
Then, I used the following query:
var geoPoint = new GeoJsonPoint<GeoJson2DGeographicCoordinates>(new GeoJson2DGeographicCoordinates(22, -5));
var query = Builders<Place>.Filter.Near(p => p.Location, geoPoint, 30000);
var result = await PlacesCollection.Find(query).ToListAsync();

Do you happen to have the stack trace of the exception you had previous to your solution? I'd like to take a look to see what the problem was.

Related

Getting a access a disposed object exception when calling QueryByIdAsync on WorkItemTrackingHttpClient

I am trying to retrieve items from TFS to perform autodocumentation of changes and fill the maximum amount possible of information to reduce the time spent doing documentation for our client, like release notes and stuff.
I use the following method to retrieve the items, which is part of a class, both included in the body:
Method:
public IEnumerable<DTO.WorkItem> GetWorkItemsFromQuery(string queryId)
{
using (WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>())
{
var queryResults =
witClient
.QueryByIdAsync(teamProjectName, new Guid(queryId))
.Result;
if (queryResults != null)
{
return queryResults
.WorkItems
.Select(item =>
{
var workitem = witClient.GetWorkItemAsync(item.Id).Result;
workitem.Fields.TryGetValue("DescriptionField", out object descriptionObject);
workitem.Fields.TryGetValue("TitleField", out object titleObject);
return new DTO.WorkItem()
{
Id = item.Id.ToString(),
Title = titleObject?.ToString() ?? string.Empty,
Description = descriptionObject?.ToString() ?? string.Empty
};
}).ToList();
}
return default(IEnumerable<DTO.WorkItem>);
}
}
}
Class:
public class VSTSIssueTrackerExplorer
{
VssConnection connection;
private readonly string teamProjectName;
public VSTSIssueTrackerExplorer(string tfsDefaultCollectionPath,
string personalAccessToken,
string teamProjectName)
{
connection =
new VssConnection(
new Uri(tfsDefaultCollectionPath),
new VssBasicCredential(string.Empty, personalAccessToken));
this.teamProjectName = teamProjectName;
}
public IEnumerable<DTO.WorkItem> GetWorkItemsFromQuery(string queryId)
{
using (WorkItemTrackingHttpClient witClient = connection.GetClient<WorkItemTrackingHttpClient>())
{
var queryResults =
witClient
.QueryByIdAsync(teamProjectName, new Guid(queryId))
.Result;
if (queryResults != null)
{
return queryResults
.WorkItems
.Select(item =>
{
var workitem = witClient.GetWorkItemAsync(item.Id).Result;
workitem.Fields.TryGetValue("DescriptionField", out object descriptionObject);
workitem.Fields.TryGetValue("TitleField", out object titleObject);
return new DTO.WorkItem()
{
Id = item.Id.ToString(),
Title = titleObject?.ToString() ?? string.Empty,
Description = descriptionObject?.ToString() ?? string.Empty
};
}).ToList();
}
return default(IEnumerable<DTO.WorkItem>);
}
}
}
The first time I call GetWorkItemsFromQuery everything runs fine and retrieves the items, as expected, transforming them with a select to a class WorkItem, shown in the following:
public class WorkItem
{
public string Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
}
After I've retrieved the items once, if I try to retrieve them again, I get the following exception: System.AggregateException("Cannot Access Disposed Object")
If I remove the using block, I can call it as many times as I need so I don't have an issue with that at all.
What I would like to know is if WorkItemTrackingHttpClient is designed to be disposed when VssConection is itself disposed or I can dispose of it when I no longer need it, I've searched online but it seems I am not capable of finding anything relevant to this matter.
Can anybody shed some light on me if not using the WorkItemTrackingHttpClient inside a using block can be a memory leak?
It seems it's by designed. When you debug the code, you could see when you secondly retrieve the work item, WorkItemTrackingHttpClient is cached in object m_cachedTypes, so you would get exception "Cannot Access Disposed Object".
I don't believe you're supposed to dispose of anything except the VssConnection itself.
Individual clients are never disposed of in Microsoft's sample code, and it appears to be the same pattern as TfsConnection in the old TFS SDK, i.e. there's precedent for only disposing the root object.

StackOverflow Exception when setting object variable

I am trying to extract data from a sql table, write it to an object and in turn put that in a list.
I'm using VS2017, C# and MS-SQL 2008.
When I run the code it extracts the data from the SQL table; dumps it into some variables (I know this isn't the fastest, I just wanted to confirm I was getting them), I instantiate the object and try to set the first value, I then get the stack overflow on the set operation.
Why is it fine setting a variable and printing to screen, but not putting it into a variable?
Error;
System.StackOverflowException HResult=0x800703E9 Message=Exception
of type 'System.StackOverflowException' was thrown.
Class;
class Company
{
public String MDWRowNumber { get => MDWRowNumber; set => MDWRowNumber = value; } //errors here on set => MDWRowNumber = value
public String MDWIdNumber { get => MDWIdNumber; set => MDWIdNumber = value; }
public String MDWCompanyName { get => MDWCompanyName; set => MDWCompanyName = value; }
}
Main;
sql = "SELECT RowNo, Id, Name FROM Company;";
command = new SqlCommand(sql, connection);
reader = command.ExecuteReader();
while (reader.Read())
{
Console.WriteLine(reader.GetValue(0).ToString());
Console.WriteLine(reader.GetValue(1).ToString());
Console.WriteLine(reader.GetValue(2).ToString());
a = reader.GetValue(0).ToString();
b = reader.GetValue(1).ToString();
c = reader.GetValue(2).ToString();
Console.WriteLine(a + " | " + b + " | " + c); // writes correct values as expected
Company company = new Company();
company.MDWRowNumber = a; /////Errors here/////
company.MDWIdNumber = b;
company.MDWCompanyName = c;
//Company company = new Company()
// {
// MDWRowNumber = reader.GetValue(0).ToString(), ///// without all junk above errors here /////
// MDWIdNumber = reader.GetValue(1).ToString(),
// MDWCompanyName = reader.GetValue(2).ToString()
// };
CompanyList.Add(company);
}
Console.WriteLine(CompanyList.First().MDWCompanyName);
reader.Close();
command.Dispose();
Here's the problem:
public String MDWRowNumber { get => MDWRowNumber;
The property calls itself - hence the stack overflow.
Either use a private variable,
private string _MDWRowNumber;
public String MDWRowNumber { get => _MDWRowNumber; set => _MDWRowNumber = value; }
or an auto property
public String MDWRowNumber { get; set; }
In your class you have
public String MDWRowNumber { get => MDWRowNumber; set => MDWRowNumber = value; }
you dont need all that, it should just be
public String MDWRowNumber { get; set; }
by putting itself in the underlying variable you've confused it.

Second call to reqContractDetails in TWS API doesn't send any notification and hangs

Trying to create kind of market scanner. Code below is supposed to return chain of option contracts. Call to TWS API is an async method that returns some data only if I get ContractEnd or Error response from TWS. On the first call to reqContractDetails() it works as expected, I get list of contracts, receive message "ContractEnd", and exit from the method.
Obstacle
In some reason, on the second call to reqContractDetails() I don't get any notification from TWS. I have to stop and restart my application, initiating new connection to the server to make it working again.
Update
After refactoring my code I'm getting an error on a second call that says "Unable to read beyond the end of the stream". Call stack looks this way.
IBLibrary.dll!IBLibrary.OptionService.GetOptionsChain.AnonymousMethod__3(IBLibrary.Messages.ErrorMessage data) Line 64
IBLibrary.dll!IBLibrary.Classes.Client.error(string str) Line 42
CSharpAPI.dll!IBApi.EReader.putMessageToQueue() Line 94
CSharpAPI.dll!IBApi.EReader.Start.AnonymousMethod__9_0() Line 48
My implementation of the wrapper in C#
public class BaseService : IDisposable
{
protected Client Sender { get; set; }
protected EReader Receiver { get; set; }
public BaseService()
{
Sender = new Client();
Sender.Socket.eConnect("127.0.0.1", 7496, 0);
Receiver = new EReader(Sender.Socket, Sender.Signal);
Receiver.Start();
var process = new Thread(() =>
{
while (Sender.Socket.IsConnected())
{
Sender.Signal.waitForSignal();
Receiver.processMsgs();
}
})
{
IsBackground = true
};
process.Start();
}
public void Dispose()
{
Sender.Socket.eDisconnect();
}
}
public class OptionService : BaseService
{
public Task<List<OptionModel>> GetOptionsChain(OptionModel query)
{
if (query == null)
{
query = new OptionModel();
}
var process = Task.Run(() =>
{
var done = false;
var id = new Random(DateTime.Now.Millisecond).Next();
var contract = new Contract
{
Symbol = query.Symbol,
SecType = "OPT",
Exchange = "SMART",
Currency = "USD",
LastTradeDateOrContractMonth = query.Expiration
};
var contracts = new List<OptionModel>();
Action<ErrorMessage> errorMessage = null;
Action<ContractDetailsMessage> contractMessage = null;
Action<ContractDetailsEndMessage> contractMessageEnd = null;
contractMessage = (ContractDetailsMessage data) =>
{
contracts.Add(new OptionModel
{
Symbol = data.ContractDetails.Contract.Symbol,
Right = data.ContractDetails.Contract.Right,
Strike = data.ContractDetails.Contract.Strike,
Expiration = data.ContractDetails.RealExpirationDate
});
};
// I receive this message at first, but not the second time
contractMessageEnd = (ContractDetailsEndMessage data) =>
{
done = true;
};
errorMessage = (ErrorMessage data) =>
{
var notifications = new List<int>
{
(int) ErrorCode.MarketDataFarmConnectionIsOK,
(int) ErrorCode.HmdsDataFarmConnectionIsOK
};
if (notifications.Contains(data.ErrorCode) == false)
{
done = true;
}
};
Sender.ErrorEvent += errorMessage;
Sender.ContractDetailsEvent += contractMessage;
Sender.ContractDetailsEndEvent += contractMessageEnd;
Sender.Socket.reqContractDetails(id, contract);
// Execute method until we get all contracts
// The econd call to reqContractDetails doesn't return
// any notification, so obviously this line hangs forever
while (done == false);
Sender.ErrorEvent -= errorMessage;
Sender.ContractDetailsEvent -= contractMessage;
Sender.ContractDetailsEndEvent -= contractMessageEnd;
return contracts;
});
return process;
}
}
As far as nobody has the answer, even IB itself, the only solution that I see is, to convert my API controller to a synchronous controller and close socket connection to IB server after every request.
Old version.
public class ServiceOptionsController : BaseServiceController
{
OptionService Service = new OptionService();
[AcceptVerbs("POST")]
public async Task<List<OptionModel>> Options([FromBody] dynamic data)
{
var selectors = data.ToObject<QueryModel>();
var optionModel = new OptionModel
{
Symbol = "MSFT",
Expiration = "201806"
};
var processes = new List<Task<List<OptionModel>>>
{
Service.GetOptionsChain(optionModel)
};
return (await Task.WhenAll(processes)).SelectMany(o => o).ToList();
}
}
Working version.
public class ServiceOptionsController : BaseServiceController
{
[AcceptVerbs("POST")]
public List<OptionModel> Options([FromBody] dynamic data)
{
var selectors = data.ToObject<QueryModel>();
var optionModel = new OptionModel
{
Symbol = "MSFT",
Expiration = "201806"
};
var optionService = new OptionService();
var processes = new List<Task<List<OptionModel>>>
{
optionService.GetOptionsChain(optionModel)
};
var items = Task.WhenAll(processes).Result.SelectMany(o => o).ToList();
optionService.Dispose(); // Ridiculous fix for ridiculous API
return items;
}
}

traffic tracking WinRT UWP windows 10

trying to receive data about received and sent bytes in every connection, that createt at the PC. I'm using WinRT UWP windows 10app, namespace Windows.Networking.Connectivity.
Here is my metode
private ulong BytesReceivedCheck(ConnectionProfile connectionProfile)
{
var currentDate = DateTime.Now;
var startDate = DateTime.Now.AddYears(-1);
//Get the ConnectionProfile that is currently used to connect to the Internet
IAsyncOperation<IReadOnlyList<NetworkUsage>> LocalUsage = connectionProfile.GetNetworkUsageAsync(startDate, currentDate, DataUsageGranularity.Total, new NetworkUsageStates());
var networkUsages = LocalUsage.GetResults();
foreach (NetworkUsage networkUsage in networkUsages)
{
return networkUsage.BytesReceived;
}
return 0;
}
I'm giving this metode as a parameter to a object
ConnectionModel model = new ConnectionModel(BytesReceivedCheck(connectionProfile));
Here is my model
public class ConnectionModel : INotifyPropertyChanged
{
ulong bytesReceived;
public ulong BytesReceived
{
get
{
return this.bytesReceived;
}
set
{
if (this.bytesReceived != value)
{
this.bytesReceived = value;
this.RaisePropertyChanged();
}
}
}
public ConnectionModel(ulong bytesReceived)
{
this.BytesReceived = bytesReceived;
}
}
I'm receiving exceprion "method invoked in unexpected time" in line var networkUsages = LocalUsage.GetResults(); in my methode. I think problem with Async, pls give me correct example of this method. I'm a begginer so sorry for maybe dumb question.

Comparing two lists and return not matching items results with error

I tried to compare two lists by using the Except method. But when I did, I got an error saying:
Cannot convert from 'Systems.Collections.Generic.List<>' to 'System.Linq.IQueryable<>'
'System.Collections.Generic.List<> does not contain a definition for 'Except' and the best extension method overload 'System.Linq.Queryable.Except(System.Linq.IQueryable, System.Collections.GEneric.IEnumerable)' has some invalid arguments
I also experienced this when I tried Intersect. I'm trying to compare Sent list and Result list (code and list shown below) and return items that does not have any match. So when I googled for how to do so, I came across the Except method as well as the Intersect.
public class Sent
{
public string Address;
public string Data;
}
public class Result
{
public string AddressOK;
public string DataOK;
}
var sent = new List<Sent>();
sent.Add(new Sent() { Address = linaddr1, Data = lindat1 });
var res = new List<Result>();
res.Add( new Result() { AddressOK = linaddr2, DataOK = lindat2 } );
//linaddr1 and 2, lindat1 and 2 contains the address and data shown in the list below
//taken from another part of the entire program
The lists look like such:
sent res
Address Data Address Data
04004C 55AA55 04004C 55AA55
040004 0720 040004 0720
040037 30
04004A FFFF 04004A FFFF
I only tried using this code:
var diff = sent.Except(res).ToList()
but as I've mentioned, it results with the aforementioned errors above.
EDIT: I edited the list. Sorry for that. It's just only a matter of the res list missing one or two or more items from the original list and then comparing both lists to see which item/s is/are missing from the res list.
Use Any:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var sent = new List<Sent>()
{
new Sent { Address = "04004C", Data = "55AA55" },
new Sent { Address = "040004", Data = "0720" },
new Sent { Address = "040037", Data = "31" },
new Sent { Address = "04004A", Data = "FFFF" }
};
var res = new List<Result> () {
new Result { AddressOK = "04004C", DataOK = "55AA55" },
new Result { AddressOK = "040004", DataOK = "0721" },
new Result { AddressOK = "040038 ", DataOK = "31" },
new Result { AddressOK = "04004A", DataOK = "FFFF" }
};
var diff =
sent.Where (s => !res.Any (r => s.Address == r.AddressOK && s.Data == r.DataOK ));
foreach (var item in diff)
{
Console.WriteLine("{0} {1}", item.Address, item.Data);
}
}
}
public class Sent
{
public string Address;
public string Data;
}
public class Result
{
public string AddressOK;
public string DataOK;
}
Output:
040004 0720
040037 31
Live Code: https://dotnetfiddle.net/ZVuiPd
The types Sent and Result are distinct types, but sent.Except(res) expects them to be the same. That's your first mistake.
The following is a simple (but incorrect) fix:
var diff =
sent
.Except(res.Select(x => new Sent() { Address = x.AddressOK, Data = x.DataOK }))
.ToList();
Even though this compiles, and runs, it doesn't remove the duplicates because your Sent doesn't override GetHashCode and Equals, hence it only compares references and not the actual properties.
You can either implement GetHashCode and Equals, or create an IEqualityComparer<Sent> to get this to work.
An IEqualityComparer<Sent> implementation might look like this:
public class SentEqualityComparer : IEqualityComparer<Sent>
{
public int GetHashCode(Sent sent)
{
return sent.Address.GetHashCode() ^ sent.Data.GetHashCode();
}
public bool Equals(Sent left, Sent right)
{
return (left.Address == right.Address) && (left.Data == right.Data);
}
}
And you would use it like so:
var diff =
sent
.Except(
res.Select(x => new Sent() { Address = x.AddressOK, Data = x.DataOK }),
new SentEqualityComparer())
.ToList();
This works as you expect.
The other option, to override GetHashCode and Equals, comes with an additional hurdle. The result of GetHashCode should not ever change throughout the lifetime of the object otherwise you can't use the object in a dictionary or any other data structure that relies on the hash code.
So, to make it work, you need to change Address & Data to be read-only.
Here is an implementation of your Sent class that will work correctly:
public sealed class Sent : IEquatable<Sent>
{
private readonly string _Address;
private readonly string _Data;
public string Address { get { return _Address; } }
public string Data { get { return _Data; } }
public Sent(string Address, string Data)
{
_Address = Address;
_Data = Data;
}
public override bool Equals(object obj)
{
if (obj is Sent)
return Equals((Sent)obj);
return false;
}
public bool Equals(Sent obj)
{
if (obj == null) return false;
if (!EqualityComparer<string>.Default.Equals(_Address, obj._Address)) return false;
if (!EqualityComparer<string>.Default.Equals(_Data, obj._Data)) return false;
return true;
}
public override int GetHashCode()
{
int hash = 0;
hash ^= EqualityComparer<string>.Default.GetHashCode(_Address);
hash ^= EqualityComparer<string>.Default.GetHashCode(_Data);
return hash;
}
}
If you are comfortable using an AOP component to automate the manual code of implementing IEquatable, another approach would be is to use Equals.Fody:
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var a = new Sent { Address = "04004C", Data = "55AA55" };
var b = new Sent { Address = "04004C", Data = "55AA55" };
Console.WriteLine(a.Equals(b)); // True with use of an AOP, False with no AOP
var sent = new List<Sent>() {
new Sent { Address = "04004C", Data = "55AA55" },
new Sent { Address = "040004", Data = "0720" },
new Sent { Address = "040037", Data = "31" },
new Sent { Address = "04004A", Data = "FFFF" }
};
var res = new List<Result>() {
new Result { AddressOK = "04004C", DataOK = "55AA55" },
new Result { AddressOK = "040004", DataOK = "0721" },
new Result { AddressOK = "040038 ", DataOK = "31" },
new Result { AddressOK = "04004A", DataOK = "FFFF" }
};
var diff =
sent.Except(
res.Select(r => new Sent { Address = r.AddressOK, Data = r.DataOK })
);
foreach (var item in diff)
Console.WriteLine("{0} {1}", item.Address, item.Data);
}
}
[Equals]
public class Sent
{
public string Address;
public string Data;
[CustomEqualsInternal]
bool CustomLogic(Sent other)
{
return other.Address == this.Address && other.Data == this.Data;
}
}
public class Result
{
public string AddressOK;
public string DataOK;
}
Output:
True
040004 0720
040037 31
If you'll do map Result to Sent very often, you can further shorten your Linq query code to..
var diff = sent.Except(res.Select(r => (Sent)r));
..by automating the mapping of Result to Sent, use implicit operator:
[Equals]
public class Sent
{
public string Address;
public string Data;
[CustomEqualsInternal]
bool CustomLogic(Sent other)
{
return other.Address == this.Address && other.Data == this.Data;
}
public static implicit operator Sent(Result r)
{
return new Sent { Address = r.AddressOK, Data = r.DataOK };
}
}
#Kurisuchin
Suppose you have 2 list and in both you have ID property based on which you want to compare both list and want to store non matching item in third list.
In this Situation following Linq Query can help out.
var result = List2.Where(p => !List1.Any(p2 => p2.ID == p.ID)).ToList();

Categories