I have a ADO.NET model entity that reflects an oracle database and a WCF Service that provides access to this ADO.NET model. In my WCF Service code, I have the following:
config.SetEntitySetAccessRule("*", EntitySetRights.AllRead);
//config.SetServiceOperationAccessRule("MyServiceOperation",ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
I have added a reference to this service in my silverlight 5 application. Then in the following code, I am getting an error:
Uri WCFUri = new Uri(HtmlPage.Document.DocumentUri, "WcfDataService.svc");
WCF_Service.Entities Database = new WCF_Service.Entities(WCFUri);
var buildings = from building in Config.Database.BUILDINGs
select building.BLDG_ID;
var buildingsQuery = (DataServiceQuery<string>)buildings;
buildingsQuery.BeginExecute(buildingsResult =>
{
foreach (string buildingId in buildingsQuery.EndExecute(buildingsResult))
BuildingsList.Items.Add(new ListItem(buildingId.Trim(), false));
BuildingListBusyIndicator.IsBusy = false;
}, null);
The error is:
Navigation properties can only be selected from a single resource. Specify a key predicate to restrict the entity set to a single instance.
I am lost on what the problem is. Thanks in advance.
The problem is that ADO.NET Data Services doesn't support projection feature.
Instead of selecting properties, you must select entities.
WRONG
var buildings = from building in Config.Database.BUILDINGs
select building.BLDG_ID;
CORRECT
var buildings = from building in Config.Database.BUILDINGs
select building;
(I understand that in your case this correction pointless, but technically this is true)
OR you can use shell, for example:
var buildings = from building in Config.Database.BUILDINGs
select new { Id = building.BLDG_ID };
Related
I have a .Net Core project running and I am utilizing 2 different databases (A MySQL db and a PostGreSQL db). I have them set up and they are both implemented in my current controller - TripController.cs
TripController.cs
public IActionResult Index()
{
var viewModels = new List<TripViewModel>();
var Dids = _tripContext.Dids.ToList();
foreach (var Did in Dids)
{
IQueryAble<Tripmetadata> trips = _tripContext.Tripmetadata.Where(t => t.Did == Did.Did);
var tripsCount = trips.Count()
//--------------------- I believe error is here ---------------------
var alias = _context.Devices.Where(d => (long.Parse(d.Did)) == Did.Did).Select(d => d.Alias).ToString();
// ------------------------------------------------------------------
var viewModel = new TripViewModel
{
TripCount = tripsCount,
didElement = Did,
Alias = alias
};
viewModels.Add(viewModel)
}
return View(viewModels);
}
_context is the MySQL db and _tripContext is the PostGreSQL db.
Both database have a field called Did which I need to use. For the PostGreSQL db I need to use it to get the amount of trips (tripCount) for a given Did. However for the MySQL db I need to use the Did to get the alias for a device.
When I try to use the above code from the TripController to get the alias for a Did I get a weird value when displaying it in my view:
Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[System.String]
as seen here:
I use a viewModel called TripViewModel which I pass to my View:
TripViewModel.cs
public class TripViewModel
{
public int TripCount {get;set;}
public long DidElement {get;set;}
public string Alias {get;set;}
}
How do I get it write the right Alias in my view?
I have tried numerous methods that doesn't yield the result I need.
I managed to find the solution.
My problem was not adding a .Single() at the end of my EF query.
I also found that this post is a duplicate. However I didn't know what my problem was until a stumpled upon this:
I'm using the OData .NET Client against the Dynamics CRM Online Web API. I can fetch a single Account entity like this:
var context = new DataServiceContext(new Uri("https://myorg.crm4.dynamics.com/api/data/v8.1/"));
// I hook into the BuildingRequest event here to add my auth header token
var accountID = new Guid("8d4e3373-454f-e611-80dc-c4346bad506c");
var account = (from a in context.Accounts
where a.Accountid == accountID
select new Account {
Name = a.Name,
Createdby = a.Createdby
}).Single();
The resulting OData query string looks like this:
https://myorg.crm4.dynamics.com/api/data/v8.1/accounts(8d4e3373-454f-e611-80dc-c4346bad506c)?$expand=createdby&$select=name
This works fine and returns the Account with just its name. My "problem" is that it also returns the entire SystemUser entity and all of its properties and nests them in CreatedBy.
{
"#odata.context":"https://myorg.crm4.dynamics.com/api/data/v8.1/$metadata#accounts(name,createdby)/$entity",
"#odata.etag":"W/\"752336\"",
"name":"Test Account 01",
"accountid":"8d4e3373-454f-e611-80dc-c4346bad506c",
"createdby":{
"#odata.etag":"W/\"752039\"",
"ownerid":"11fd590a-6147-e611-80d8-c4346bad62c0",
"_queueid_value":"16fd590a-6147-e611-80d8-c4346bad62c0",
"_createdby_value":null,
... lots of other properties here ...
"address1_stateorprovince":null,
"displayinserviceviews":false,
"timezoneruleversionnumber":null
}
}
I want to return only specific properties of the SystemUser entity which would use an OData query like this (the important part is $expand=createdby($select=fullname)):
https://myorg.crm4.dynamics.com/api/data/v8.1/accounts(8d4e3373-454f-e611-80dc-c4346bad506c)?$expand=createdby($select=fullname)&$select=name
If I run the above query I now get the Account entity with just its name and for CreatedBy it only has the Fullname property of the SystemUser.
I can't find a way to do this in the initial LINQ query. I tried this and got errors:
var account = (from a in context.Accounts
where a.Accountid == accountID
select new Account {
Name = a.Name,
Createdby = new SystemUser { Fullname = a.Createdby.Fullname }
}).Single();
Is it possible to select just specific properties of nested entities rather than the whole thing?
It's not the end of the world to return the entire thing, I just like to return only the data I want if it can be helped.
Edit 17/08/2016: After some further troubleshooting it appears that creating a new SystemUser and populating only the full name property does actually generate the correct OData query string. If I run it manually I get the correct result. I still get errors running it through the OData Client model. The error is:
The expected property 'Createdby' could not be found while processing an entry. Check for null before accessing this property.
The property is not null, it can't be by definition. I think it might be looking for CreatedBy on the SystemUser entity rather than on Account, but I'm not sure.
I need some help to figure out how to search my SQLite database.
I am trying to search for their cake and stars; this is my connection:
// Create our connection
string folder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
var db = new SQLiteConnection(System.IO.Path.Combine(folder, "OnTopFiles.db"));
db.CreateTable<User>();
// Insert note into the database
var note = new User { cake = "frosting marble", stars = "5" };
db.Insert(note);
// Show the automatically set ID and message.
Console.WriteLine("{0}: {1}", note.cake, note.stars);
You can use a WHERE query:
var query = conn.Table<User>().Where(u => u.Cake.StartsWith("frosting"));
foreach (var user in query)
{
// Use user.cake or other properties
}
Alternatively, you can use SQL directly. The library you are using hides the SQLite SQL so most of the SQLite syntax is hidden from you. This library is pure .NET Standard and runs on all Xamarin Platforms. You have the full power of SQL so searching is the same as other platforms.
https://github.com/MelbourneDeveloper/SQLite.Net.Standard
Referencing the following IPP Documentation:
https://developer.intuit.com/docs/0025_quickbooksapi/0055_devkits/0150_ipp_.net_devkit_3.0/query_filters
I made the assumption that the following code using the Linq Extentions Projection would alter the request and reduce the payload of the response by only querying for the requested fields and only including those fields (narrow result set) in the response:
public List<ShortAccount> GetFullShortAccountList(bool logRequestResponse)
{
var accounts = new List<ShortAccount>();
var accountQueryService = new QueryService<Account>
(GetIppServiceContext(logRequestResponse));
var selected = accountQueryService.Select(a => new { a.Id, a.Name });
foreach (var account in selected)
{
accounts.Add(new ShortAccount { Id = account.Id, Name = account.Name });
}
return accounts;
}
Now the behavior of this method is as expected, but if I look at the request/response logs (or the actual request and response using Fiddler) the request doesn't change -- it is still "Select * from Account", and the response still includes all the other properties in the Account entity.
In other words, the payload is not reduced one iota.
Am I doing something wrong here? Or do I just understand this incorrectly?
How can I use the SDK to generate a query that would look more like "Select Id, Name from Account", and only return that result set?
Related question -- if this mode of query filtering does not reduce the payload, what is its purpose? You might as well get the whole shebang and just take the fields you need?
Thanks in advance.
That's right #Barrick. The implementation of our query providers is not exactly the same as the standard LINQ. So, Stephan, that's the issue.
If you just want to get specific fields I would suggest you to use IDSQuery like:
QueryService<Account> AccQueryService22 = new QueryService<Account>(context);
var t13 = AccQueryService22.ExecuteIdsQuery("Select Id, Name From Account Where Active in (true, false)");
I will forward the feedback to our team.
Thanks!
I am trying to update a row in a (typed) MongoDB collection with the C# driver. When handling data of that particular collection of type MongoCollection<User>, I tend to avoid retrieving sensitive data from the collection (salt, password hash, etc.)
Now I am trying to update a User instance. However, I never actually retrieved sensitive data in the first place, so I guess this data would be default(byte[]) in the retrieved model instance (as far as I can tell) before I apply modifications and submit the new data to the collection.
Maybe I am overseeing something trivial in the MongoDB C# driver how I can use MongoCollection<T>.Save(T item) without updating specific properties such as User.PasswordHash or User.PasswordSalt? Should I retrieve the full record first, update "safe" properties there, and write it back? Or is there a fancy option to exclude certain fields from the update?
Thanks in advance
Save(someValue) is for the case where you want the resulting record to be or become the full object (someValue) you passed in.
You can use
var query = Query.EQ("_id","123");
var sortBy = SortBy.Null;
var update = Update.Inc("LoginCount",1).Set("LastLogin",DateTime.UtcNow); // some update, you can chain a series of update commands here
MongoCollection<User>.FindAndModify(query,sortby,update);
method.
Using FindAndModify you can specify exactly which fields in an existing record to change and leave the rest alone.
You can see an example here.
The only thing you need from the existing record would be its _id, the 2 secret fields need not be loaded or ever mapped back into your POCO object.
It´s possible to add more criterias in the Where-statement. Like this:
var db = ReferenceTreeDb.Database;
var packageCol = db.GetCollection<Package>("dotnetpackage");
var filter = Builders<Package>.Filter.Where(_ => _.packageName == packageItem.PackageName.ToLower() && _.isLatestVersion);
var update = Builders<Package>.Update.Set(_ => _.isLatestVersion, false);
var options = new FindOneAndUpdateOptions<Package>();
packageCol.FindOneAndUpdate(filter, update, options);
Had the same problem and since I wanted to have 1 generic method for all types and didn't want to create my own implementation using Reflection, I end up with the following generic solution (simplified to show all in one method):
Task<bool> Update(string Id, T item)
{
var serializerSettings = new JsonSerializerSettings()
{
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
var bson = new BsonDocument() { { "$set", BsonDocument.Parse(JsonConvert.SerializeObject(item, serializerSettings)) } };
await database.GetCollection<T>(collectionName).UpdateOneAsync(Builders<T>.Filter.Eq("Id", Id), bson);
}
Notes:
Make sure all fields that must not update are set to default value.
If you need to set field to default value, you need to either use DefaultValueHandling.Include, or write custom method for that update
When performance matters, write custom update methods using Builders<T>.Update
P.S.: It's obviously should have been implemented by MongoDB .Net Driver, however I couldn't find it anywhere in the docs, maybe I just looked the wrong way.
Well there are many ways to updated value in mongodb.
Below is one of the simplest way I choose to update a field value in mongodb collection.
public string UpdateData()
{
string data = string.Empty;
string param= "{$set: { name:'Developerrr New' } }";
string filter= "{ 'name' : 'Developerrr '}";
try
{
//******get connections values from web.config file*****
var connectionString = ConfigurationManager.AppSettings["connectionString"];
var databseName = ConfigurationManager.AppSettings["database"];
var tableName = ConfigurationManager.AppSettings["table"];
//******Connect to mongodb**********
var client = new MongoClient(connectionString);
var dataBases = client.GetDatabase(databseName);
var dataCollection = dataBases.GetCollection<BsonDocument>(tableName);
//****** convert filter and updating value to BsonDocument*******
BsonDocument filterDoc = BsonDocument.Parse(filter);
BsonDocument document = BsonDocument.Parse(param);
//********Update value using UpdateOne method*****
dataCollection.UpdateOne(filterDoc, document);
data = "Success";
}
catch (Exception err)
{
data = "Failed - " + err;
}
return data;
}
Hoping this will help you :)