Using the odata-v4 service connection in visual studio C# .NET, I get an entity of type testDefinition. testDefinition has property called features which is a collection of entities of type feature.
In the DB, testDefinition to feature is many to many with a junction table.
In my code, I add a service reference to a web service serving the EDMX of the DB.
Code gets generated correctly and I run:
var dsc = new Container(new Uri("http://webserver/webapi/odata/"));
var someFeature = new Feature
{
name = $"Sample feature created with C# {DateTime.UtcNow}",
};
var someOtherFeature = new Feature
{
name = $"Sample other feature created with C# {DateTime.UtcNow}",
};
dsc.AddToFeature(someFeature);
dsc.AddToFeature(someOtherFeature);
dsc.SaveChanges();
var someTestDefinition = new TestDefinition
{
name = $"Sample test created with C# {DateTime.UtcNow}",
description = $"A nice succinct description",
};
dsc.AddToTestDefinition(someTestDefinition);
dsc.SaveChanges();
someTestDefinition.features.Add(someFeature);
someTestDefinition.features.Add(someOtherFeature);
dsc.SaveChanges();
The problem is the mapping from the test definition to features is not recorded in the database.
Has anyone encountered this issue, or better yet, resolved it?
For Reference:
I can't say when this was implemented but it works in later versions, the earliest verison I can confirm this against is OData.Client v 7.6.2
If this is an issue for any new users on current versions of the OData Client and Server libraries it generally indicates that the schema is not correctly configured or published.
Also check that the API uses a similarly current OData runtime, the above test was performed against API with Microsoft.AspNet.OData v7.3.0
Related
My goal: Create a Windows form app that queries via GraphQl to an existing online database.
What I've done:
To simulate a graphQl server I've followed the official graphql-node Tutorial till the end. So now I'm able to query from the GraphQl playground and get a response. This server runs on localhost:4000.
I've created a windows form app in Visual Studio that queries in graphQl to an internal database containing mocked data. E.g.
My Form.cs class contains this code, where I execute the query onButtonClick
private void button1_Click(object sender, EventArgs e)
{
var schema = Schema.For(#"
type Jedi {
name: String,
side: String,
id: ID
}
type Query {
hello: String,
jedis: [Jedi],
jedi(id: ID): Jedi
}", _ => { _.Types.Include<Query>(); }
);
var json = schema.Execute(_ =>
{
_.Query = "{jedis { name, side } }";
});
System.Diagnostics.Debug.WriteLine(json);
label1.Text = json;
}
After I execute the query my Query.cs class will recognize it and resolve the query
class Query
{
[GraphQLMetadata("jedis")]
public IEnumerable<Jedi> GetJedis()
{
return StarWarsDB.GetJedis();
}
}
This is my Current internal DB
class StarWarsDB
{
public static IEnumerable<Jedi> GetJedis()
{
return new List<Jedi>() {
new Jedi(){ Id = 1, Name ="Luke", Side="Light"},
new Jedi(){ Id = 2, Name ="Yoda", Side="Light"},
new Jedi(){ Id = 3, Name ="Darth Vader", Side="Dark"}
};
}
}
The next step i want to do:
Now, I've found a lot of examples online on how to query a db but they were always made internally in visual Studio. What I wanted to do is connecting to my personal DB running on my localHost for now (the one i made following the graphql-node Tutorial) and query it with graphQl. Then take the JSON response and print it somewhere.
You are mixing it up a little bit. For starters you don't need to have a schema declaration on your client.
If I understood you correctly you are using webforms, and want to acess a api service on the backend which will return you data.
So in that case you need a graphql "Client" in your webforms project, with which you "Connect" to a endpoint like your prisma api, and afterwards you only send querys or mutations to the api as a request.
Here is the link for the client, you install it as a nuget, and follow the documentation.
https://github.com/graphql-dotnet/graphql-client
So in most simple terms explained, graphqlClient sends a query to => endpoint(in this case your prisma api) which gets data => from your database.
Client(query) => Api(select * datasource) => DB(SQL) => Api(returns data) => Client(deserialise) => bind to UI => see the output.
GraphQL is a query language for your API, and a server-side runtime for executing queries by using a type system you define for your data. GraphQL isn't tied to any specific database or storage engine and is instead backed by your existing code and data. - graphql.org
Hi Zayed
Maybe I misunderstand your explanation but you cannot query directly to the database using GraphQL. You'll need an API project between your connection and the GraphQL logic. You'll post your GraphQL scheme to the API endpoint and it will return, based on your endpoint, the correct data structure.
I found a good website where it will be explained step by step on how to implement it in ASP.NET CORE 2.
Hope this helps.Good luck!
I started my Visual Studio project from AWS SDK template. It uses IDynamoDBContext in the function and IAmazonDynamoDB in the tests.
Everything worked to save and received documents when I received them with an id (hash). But it stopped to work when I added a range to my table. All my test were against AWS dynamoDb. But I got it to work in 2 ways. The first way were when I downloaded the local instance of dynamoDb. The second were when I replaced IDynamoDBContext to IAmazonDynamoDB in my function (so it used the same interface in both the function and in my test class). I don't know what the correct solution is, but why use 2 interfaces in the first place? Should I keep digging in why it didn't work with different interfaces or should I only use one of them?
// IDynamoDBContext (default) - Didn't save my item (did save it in local DynamoDB)
var test = new Test
{
UserId = "Test",
Id = 1
};
await DDBContext.SaveAsync<Test>(test);
// IAmazonDynamoDB - Did save my item
var putItemRequest = new PutItemRequest
{
TableName = "TestTable",
Item = new Dictionary<string, AttributeValue>()
{
{ "UserId", new AttributeValue { S = "Test" }},
{ "Id", new AttributeValue { N = "1" }}
}
};
await DDBContext.PutItemAsync(putItemRequest);
My test:
var item = new GetItemRequest
{
TableName = "TestTable",
Key = new Dictionary<string, AttributeValue>
{
{ "UserId", new AttributeValue { S = "Test" } },
{ "Id", new AttributeValue { N = "1" } },
},
};
Assert.True((await this.DDBClient.GetItemAsync(item)).Item.Count > 0);
We probably need someone on the AWS .Net SDK team to speak to this but here is my best insight.
Amazon documentation is always fun.
The documentation does not make it overly clear but IDynamoDBContext is found in the Amazon.DynamoDbv2.DataModel namespace which is used for object persistence data access.
So I think the IAmazonDynamoDB interface is used for general API calls against the DynamoDB service. The two modes have overlapping functionality in that both can work with given items in a dynamoDb table.
The docs, of course, are really clear in that for IDynamoDbContext it says
Context interface for using the DataModel mode of DynamoDB. Used to
interact with the service, save/load objects, etc.
https://docs.aws.amazon.com/sdkfornet/v3/apidocs/Index.html
For IAmazonDynamoDB it says
Interface for accessing DynamoDB Amazon DynamoDB
IAmazonDynamoDB is from the Amazon.DynamoDbv2 namespace and IDynamoDBContext is found in the Amazon.DynamoDbv2.DataModel.
If you look at the documentation for them both though you will see by looking at the methods the actions each can performance are very different.
IAmazonDynamoDb allows you to interact and work more with DynamoDb via:
Creating tables
Deleting tables
Creating global indexes and backups
etc.
You can still work directly with items but the number of API calls
available via this interface is larger and allows working with
the overall DynamoDB service.
While IDynamoDBContext allows you work directly with items in a given DynamoDb table with methods like:
Save
Query
Scan
Load
Consistency is always key in programming so always use the same interface for areas that are meant to do the same level of work. So your code and tests should be using the same interface as they are focused on the same work scope. Hopefully based on that additional clarification you know what interface you are after. If all your code is trying to do is work with items in a DynamoDb table then IDynamoDBContext is probably what you are after.
I have a many to many custom relationship company_a_c between Accounts and Contacts in CRM 2013. I am now trying to add a relationship via the oData (REST) web services, but have run into some difficulties. I created a standard c# proxy class to the oData web services.
Attempt 1 (create relationship object):
var crmRelationship = new company_a_c();
crmRelationship.accountid = account.AccountId;
crmRelationship.contactid = contact.ContactId;
crmService.AddTocompany_a_cSet(crmRelationship);
crmService.SaveChanges();
Result: Error "The 'Create' method does not support entities of type CRM 2013 'company_a_c'
Attempt 2 (create via objects):
account.company_A_C.Add(contact);
crmService.UpdateObject(account);
crmService.SaveChanges();
Result: No error thrown, but relationship not created
I'm sure I'm going about this the wrong way (new to oData) so any help as to the right way to setup these type of relationships would be appreciated.
try the following:
EntityReferenceCollection entityCollection = new EntityReferenceCollection();
entityCollection.Add(new EntityReference(Contact.EntityLogicalName, contact.ContactId));
Relationship crmRelationship = new Relationship(company_a_c.EntityLogicalName);
crmService.Associate(Account.EntityLogicalName, account.AccountId, crmRelationship, entityCollection);
Looks like SetLink was the wrong one, but AddLink was what I should have been after.
crmService.AddLink(account, "company_a_c", contact);
crmService.SaveChanges();
I am trying to consume OData from a windows forms. So, what i have done to now is create a new project, i added a web service reference to the OData service and try to consume it.
My code is:
var VistaEntities = new VrExternalEntities("serviceURI");
var query = VistaEntities.VRtblCinemaType
.Where(
x =>
x.VRtblCinema_Operators
.Any
(
z =>
z.VRtblSessions
.Any
(
y =>
y.Session_dtmDate_Time > DateTime.Now
)
)
)
.Select
(
x =>
new
{
x.CinType_strCode,
x.CinType_strDescription
}
);
If i remove the Where clause it works. If i do it says that Any is not supported. I know i have to set MaxProtocolVersion to V3 but i do not know how to do it. I don't have an entity context or anything else. I only have what i have stated above.
Please provide steps on how to accomplish that.
Thanks in advance.
Giannis
You must retrieve the configuration of your DataService and set the MaxProtocolVersion of its behavior to V3.
The best place to do this is certainly in the InitializeService static method you can define in your service class, which will be given the proper configuration object as its config parameter by the environment. It will only be invoked once, typically at the first request.
Note #1: You need WCF Data Services 5.0 or greater. The best way to get it is probably via the Server NuGet package.
Note #2: Oddly enough, the DataServiceProtocolVersion type, although in the Common namespace, is included in the Client assembly (Microsoft.Data.Services.Client, provided by the Client NuGet package). I suggested a better organization here.
public class Vista : DataService<VistaContext>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule(...);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;
...
}
}
Update:
The client may indeed specify the desired version in the requests by using the DataServiceVersion HTTP header. It's currently recommended that you specify and support a range of versions using the MinDataServiceVersion and MaxDataServiceVersion headers if you can, for obvious reasons. Note however that the MinDataServiceVersion will be removed in OData 4.0 (see appendix E.1 of part 1 and "What's new" documents drafts).
The relevant documentation for the WCF Data Services 5.x implementation is available here. The documentation specific to the client seems pretty scarce, but looking at the reference you can see that you must use this constructor for the DataServiceContext to specify the maximum protocol version, and it looks like you cannot change it at any one point for subsequent requests without rebuilding a new context. You may attempt to fiddle with the headers directly, but I wouldn't expect it to work reliably (or at all).
So, to answer your question, you really need control over how you create the context for the client.
I am trying to build a core application that uses plugins so that the core never changes and each time we get a new client we write a module for them. We implement a interface called IClientPlugin with the new customer class.
This is using Compact Framework 3.5 and windows mobile 6.5.3.
So here is what I need to acheive:
this is a warehouse management system. The first task is to receive in the product from a truck scanning barcodes off packages with the handheld device.
The core module for this is started when the person clicks the receiving menu item.
the core method is - callClientMethod()
I know the client name and it is stored in a global variable at login and the class will be {clientname}.cs
and contain a method called processReceiving().
I know how to instantiate this object.
The question is: is there a way I can dynamically create a instance of the client class without hardcoding case statements?
For example suppose I have 2 clients Acme and Widgets. They each get a client class, namely Acme.cs and Widgets.cs
If I login as Acme or Widgets I want the code to dynamically create a instance of the Client class that I logged in as so that the core code does not have to change as I add more clients as long as I add a module for them.
psuedo example:
var myClient = New (Clientname)();
Is this possible or is there a better design approach or is the switch/case statement a neccessary evil?
You can use reflection to create objects dynamically.
There are many ways to load a type or assembly. Lets start with a simple one:
Type clientType = Type.GetType("AssemblyName, TypeName");
IClientPlugin clientPlugin =
(IClientPlugin)Activator.CreateInstance(clientType);
If your client is named myClient1 and you have the convention, that your assemblies are named for example like Clients.ClientName.dll then you can write a function:
IClientPlugin CreatePluginInstance(string clientName) {
string typeName = string.Format("Clients.{0}, {0}", clientName);
Type clientType = Type.GetType(typeName);
IClientPlugin clientPluginInstance =
(IClientPlugin)Activator.CreateInstance(clientType);
return clientPluginInstance;
}
EDIT
If your plugin classes are located in the same assembly as your main project, you can simplify the call of Type.GetType to just specify the classname:
Type.GetType(clientName);
var myClient = Activator.CreateComInstanceFrom("Acme.dll","Acme");
Where you can parametrize the Assembly name and the type name.