I'm trying to rename a collection in MongoDB with RenameCollectionOperation(). I found the documentation of it but I can't get it working.
https://mongodb.github.io/mongo-csharp-driver/2.4/apidocs/html/T_MongoDB_Driver_Core_Operations_RenameCollectionOperation.htm
private readonly MongoClient _mongoClient = new MongoClient("connectionString");
public IMongoCOllection<RenameCollection> ToRenameCollection => _MognoClient.GetDatabase().GetCollection<RenameCollection>("RrenameCollection");
var checkIfCollectionExists = ToRenameCollection.Find(new BsonDocument());
if (checkIfCollectionExists != null)
{
var test = new MongoDB.Driver.Core.Operations.RenameCollectionOperation(
new CollectionNamespace("database", "RrenameCollection"),
new CollectionNamespace("database", "RenameCollection"),
new MessageEncoderSettings()
);
}
I figured it out.
It seems I needed to create a method that only returned the database.
private readonly MongoClient _mongoClient = new MongoClient("connectionString");
public IMongoDatabase Database => _mongoClient.GetDatabase();
private async Task<bool> CollectionExistsAsync(string collectionName)
{
var filter = new BsonDocument("name", collectionName);
//filter by collection name
var collections = await _mongo.Database.ListCollectionsAsync(new ListCollectionsOptions { Filter = filter });
//check for existence
return await collections.AnyAsync();
}
var oldSmsLogExists = await CollectionExistsAsync("RrenameCollection").ConfigureAwait(false);
if (oldSmsLogExists)
_mongo.Database.RenameCollection("RrenameCollection", "RenameCollection");
Related
I have a situation like this:
var mongoClient = new MongoClient("connection-bla-bla");
var mongoDB = mongoClient.GetDatabase("db-name");
using (var session = mongoDB.Client.StartSession())
{
session.StartTransaction();
var collection = mongoDB.GetCollection<Rec>("collectionName");
collection.InsertOne(new Rec() { Name = "Record1" });
collection.InsertOne(new Rec() { Name = "Record2" });
session.CommitTransaction();
}
This code works quite fine, Record1 and Record2 are written.
However, when i try this ...
var mongoClient = new MongoClient("connection-bla-bla");
var mongoDB = mongoClient.GetDatabase("db-name");
using (var session = mongoDB.Client.StartSession())
{
session.StartTransaction();
var collection = mongoDB.GetCollection<Rec>("collectionName");
collection.InsertOne(new Rec() { Name = "Record1" });
if (DateTime.UtcNow > DateTime.MinValue) throw new Exception("Bad things happens");
collection.InsertOne(new Rec() { Name = "Record2" });
session.CommitTransaction();
}
... Record1 is written, even the transaction is not comitted. I guess I miss here something, but have no clue what.
Thanks for code correction.
In order to use the transaction, you need to specify the session when calling the insert commands:
var mongoClient = new MongoClient("connection-bla-bla");
var mongoDB = mongoClient.GetDatabase("db-name");
using (var session = mongoDB.Client.StartSession())
{
session.StartTransaction();
var collection = mongoDB.GetCollection<Rec>("collectionName");
collection.InsertOne(session, new Rec() { Name = "Record1" });
if (DateTime.UtcNow > DateTime.MinValue) throw new Exception("Bad things happens");
collection.InsertOne(session, new Rec() { Name = "Record2" });
session.CommitTransaction();
}
There are overloads for various write commands that accept the session. See this link for details.
I wish to automate the transfer of ether to a list of people.
Assume the list is in a csv.
I wrote some code to automate the process.
class Program
{
int nonce = 0;
static void Main(string[] args)
{
var account = SetupAccount();
var recipients = ReadCsv();
var web3Init = GetConnection();
nonce = web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(account.Address).Result;
//var recipients = new List<Records>() { new Records() { Value = 10000000000000000, Address = "0x5CC494843e3f4AC175A5e730c300b011FAbF2cEa" } };
foreach (var recipient in recipients)
{
try
{
var web3 = GetConnection();
var receipt = SendEther(account, recipient, web3).Result;
}
catch (System.Exception)
{
MessageBox.Show("Failed");
}
Thread.Sleep(30000);
}
}
private static async Task<TransactionReceipt> SendEther(Account account, Records recipient, Web3 web3)
{
var transactionPolling = web3.TransactionManager.TransactionReceiptService;
//var currentBalance = await web3.Eth.GetBalance.SendRequestAsync(account.Address);
//assumed client is mining already
//when sending a transaction using an Account, a raw transaction is signed and send using the private key
return await transactionPolling.SendRequestAndWaitForReceiptAsync(() =>
{
var transactionInput = new TransactionInput
{
From = account.Address,
//Gas = new HexBigInteger(25000),
GasPrice = new HexBigInteger(10 ^ 10),
To = recipient.Address,
Value = new HexBigInteger(new BigInteger(recipient.Value)),
Nonce = nonce
};
var txSigned = new Nethereum.Signer.TransactionSigner();
var signedTx = txSigned.SignTransaction(account.PrivateKey, transactionInput.To, transactionInput.Value, transactionInput.Nonce);
var transaction = new Nethereum.RPC.Eth.Transactions.EthSendRawTransaction(web3.Client);
nonce++;
return transaction.SendRequestAsync(signedTx);
});
}
private static Web3 GetConnection()
{
return new Web3("https://mainnet.infura.io");
}
private static Account SetupAccount()
{
var password = "#Password";
var accountFilePath = #"filePath";
return Account.LoadFromKeyStoreFile(accountFilePath, password);
}
private static List<Records> ReadCsv()
{
string filePath = #"C:\Users\Potti\source\repos\ConversionFiles\XrcfRecipients.csv";
if (File.Exists(filePath))
{
using (StreamReader stream = new StreamReader(filePath))
{
CsvReader reader = new CsvReader(stream, new Configuration
{
TrimOptions = TrimOptions.Trim,
HasHeaderRecord = true,
HeaderValidated = null
});
reader.Configuration.RegisterClassMap<RecordMapper>();
return reader.GetRecords<Records>().ToList();
}
}
else
{
return null;
}
}
}
class Records
{
public string Address { get; set; }
public decimal Value { get; set; }
}
sealed class RecordMapper : ClassMap<Records>
{
public RecordMapper()
{
Map(x => x.Address).Name("Address");
Map(x => x.Value).Name("Value");
}
}
How do i modify the process to execute all the transactions at once instead of waiting for each to complete? (Fire and forget)
Also, are there any security considerations of doing this?
What you are currently doing is waiting for each transaction to be mined. What you can do is the following:
var account = new Account("privateKey"); // or load it from your keystore file as you are doing.
var web3 = new Web3(account, "https://mainnet.infura.io");
First create a web3 instance using the same Account object, because we are using an account with a private key, Nethereum will sign your transactions offline before sending them.
Now using the TransactionManager, you can then send a transaction per each recepient
var transactionHashes = new List<string>();
foreach(var recepient in recepients){
var transactionInput = new TransactionInput
{
From = account.Address,
GasPrice = Web3.Convert.ToWei(1.5, UnitConversion.EthUnit.Gwei);,
To = recipient.Address,
Value = new HexBigInteger(new BigInteger(recipient.Value)),
};
var transactionHash = web3.Eth.TransactionManager.SendTransactionAsync(transactionInput);
transanctionHashes.Add(transactionHash);
}
Note that when Nethereum uses the same instance of an Account and TransactionManager (or Web3 in this scenario) it creates a default NonceMemoryService, so you don't need to keep track of your nonces (Transaction number), to sign the transaction.
Also I have done a conversion for the GasPrice from Gwei to Wei, as an example of Unit conversions, I assume that you already have converted to Wei the Ether amounts you are going to send.
Finally, another note, to further simplify this, there is an upcoming EtherTransferService which allows you to input Ether amounts and Gwei price amounts to avoid doing conversions. Also the gas price will be calculated for you, if not passed any parameter.
web3.Eth.GetEtherTransferService().TransferEtherAsync("toAddress", EtherAmount);
I used to use this command FindOne to query the result from mongoDB with C# in the past and it can be used at that time. But now I use the same code but it doesn't work. What should I use instead of FindOne?
My code is like this:
var connectionString = "mongodb://localhost";
var client = new MongoClient(connectionString);
var database = client.GetDatabase("extend");
var collection = database.GetCollection<Entity>("user");
var query = Query<Entity>.EQ(e => e.user_id, int.Parse(targetUser.CurrentUser));
var entity_TargetUser = collection.FindOne(query);
When I try to run it, I got this error
Error CS1061: 'IMongoCollection<Entity>' does not contain a definition for 'FindOne' and no extension method 'FindOne' accepting a first argument of type 'IMongoCollection<Entity>' could be found (are you missing a using directive or an assembly reference?) (CS1061)
What command that I can use instead of FindOne?
You are dealing with an id, so I assume each one is unique - if they aren't, they should be. Assuming user_id is unique then I would do the following
public static class MongoDataService
{
public static async Task<List<BsonDocument>> GetDocumentCollectionAsync(
MongoClient client, FilterDefinition<BsonDocument> filter,
string databaseName, string collectionName, CancellationToken token,
int? limit = null)
{
return await Task.Run(async () =>
{
long i = 1;
List<BsonDocument> items = new List<BsonDocument>();
var collection = GetCollection<BsonDocument>(client, databaseName, collectionName);
using (var cursor = await collection.FindAsync(filter))
{
while (await cursor.MoveNextAsync())
{
var batch = cursor.Current;
foreach (var doc in batch)
{
items.Add(doc);
if (token.IsCancellationRequested || i == limit)
return items;
i++;
}
}
}
return items;
}, token);
}
}
This method with the correct filter will return single documents, or can be used to return batches of documents again according to the imposed filter. Calling this method for your case, you can do
var filterBuilder = Builders<BsonDocument>.Filter;
var filter = filterBuilder.Eq("user_id", int.Parse(targetUser.CurrentUser));
var documents = await MongoDataService.GetDocumentCollectionAsync(client, filter, "extend", "user", token, null);
There are other methods to do what you want, but this should do what you want.
Note, I am assuming you are using the offical MongoDB.Driver.
you can do something like this:
var connectionString = "mongodb://localhost";
var client = new MongoClient(connectionString);
var database = client.GetDatabase("extend");
var collection = database.GetCollection<Entity>("user");
var query = Query<Entity>.EQ(e.user_id,int.Parse(targetUser.CurrentUser));
var entity_TargetUser = collection.AsQueryable().where(query).single();
or
var connectionString = "mongodb://localhost";
var client = new MongoClient(connectionString);
var database = client.GetDatabase("extend");
var collection = database.GetCollection<Entity>("user");
var entity_TargetUser = collection.AsQueryable().where(e=>e.user_id ==
int.Parse(targetUser.CurrentUser)).single();
I am doing some update in crm using ssis. I tried to close some cases in crm based on certain conditions. This is my sample code in public override void Input0_ProcessInputRow(Input0Buffer Row) method.
public override void Input0_ProcessInputRow(Input0Buffer Row)
{
// Create a Entity object of type 'case'
Entity caseEnt = new Entity("incident");
Entity incidentResolution= new Entity("incidentresolution");
incidentResolution.Attributes.Add("incidentid", new
EntityReference("incident", Row.DEVCaseGUID));
caseEnt["incidentid"] = Row.DEVCaseGUID;
//organizationservice.Update(caseEnt);
//Changes added here by //
EntityCollection collection= GetAssociatedActivities(new EntityReference("incident", Row.DEVCaseGUID))
foreach (Entity activity in collection.Entities)
{
CancelActivity(activity, organizationservice);
}
// Changes added here //
// Close the incident with the resolution.
var closeIncidentRequest = new CloseIncidentRequest
{
IncidentResolution = incidentResolution,
Status = new OptionSetValue(5)
};
organizationservice.Execute(closeIncidentRequest);
}
private EntityCollection GetAssociatedActivities(EntityReference regarding)
{
QueryExpression query = new QueryExpression { EntityName = "activitypointer", ColumnSet = new ColumnSet(new string[] { "activitytypecode" }) };
query.Criteria.AddCondition("regardingobjectid", ConditionOperator.Equal, regarding.Id);
query.Criteria.AddCondition("statecode", ConditionOperator.NotEqual, 1); //ignore completed
EntityCollection collection = organizationservice.RetrieveMultiple(query);
return collection
}
// Cancel an Activity
private static void CancelActivity(Entity entity, IOrganizationService service)
{
EntityReference moniker = new EntityReference();
if (entity.LogicalName == "activitypointer")
{
if (entity.Attributes.Contains("activityid") & entity.Attributes.Contains("activitytypecode"))
{
moniker.LogicalName = entity.Attributes["activitytypecode"].ToString();
moniker.Id = (Guid)entity.Attributes["activityid"];
SetStateRequest request = new SetStateRequest();
request.EntityMoniker = moniker;
request.State = new OptionSetValue(2);
request.Status = new OptionSetValue(-1);
SetStateResponse response = (SetStateResponse)service.Execute(request);
}
}
}
Row.DEVCaseGUID is the GUID of the Case.
statuscode is 5 for closed.
statecode is 2 for Resolved.
I tried follow this example but no success. Or is there any simple way to achieve this ?
Closing a Case in CRM is different than setting state/statuscode.
An Intermediate entity named IncidentResoultion is created when a case is closed.
You can try the following code to close the case programmatically.
Entity incidentResolution= new Entity("incidentresolution");
incidentResolution.Attributes.Add("incidentid", new
EntityReference("incident", Row.DEVCaseGUID));
// Close the incident with the resolution.
var closeIncidentRequest = new CloseIncidentRequest
{
IncidentResolution = incidentResolution,
Status = new OptionSetValue(5)
};
organizationservice.Execute(closeIncidentRequest);
Please note that a case can only be marked as Closed/Completed only if all the activititesregarding that Case are completed.
Update 09-Nov-2017: Adding code for closing related activities regarding CASE
private List<Entity> GetAssociatedActivities(EntityReference regarding)
{
QueryExpression query = new QueryExpression { EntityName = "activitypointer", ColumnSet = new ColumnSet(new string[] { "activitytypecode" }) };
query.Criteria.AddCondition("regardingobjectid", ConditionOperator.Equal, regarding.Id);
query.Criteria.AddCondition("statecode", ConditionOperator.NotEqual, 1); //ignore completed
EntityCollection activities = organizationservice.RetrieveMultiple(query);//change collection to activities
foreach (Entity activity in activities.Entities)
{
CancelActivity(activity, organizationservice);
}
}
// Cancel an Activity
private static void CancelActivity(Entity entity, IOrganizationService service)
{
EntityReference moniker = new EntityReference();
if (entity.LogicalName == "activitypointer")
{
if (entity.Attributes.Contains("activityid") & entity.Attributes.Contains("activitytypecode"))
{
moniker.LogicalName = entity.Attributes["activitytypecode"].ToString();
moniker.Id = (Guid)entity.Attributes["activityid"];
SetStateRequest request = new SetStateRequest();
request.EntityMoniker = moniker;
request.State = new OptionSetValue(2);
request.Status = new OptionSetValue(-1);
SetStateResponse response = (SetStateResponse)service.Execute(request);
}
}
}
https://www.magnetismsolutions.com/blog/roshanmehta/2012/2/16/Dynamics_CRM_2011_Closing_all_Related_Activities_for_a_Record.aspx
https://msdynamicscrmblog.wordpress.com/2013/06/18/there-are-still-open-activities-associated-with-this-case-when-resolving-a-case-in-dynamics-crm-2011/
I am writing below code to retrieve all entities from Azure table. But I am kind of stuck up in passing entity resolver delegate. I could not find much reference on MSDN.
Can some one please point out, how to use EntityResover in below code?
public class ATSHelper<T> where T : ITableEntity, new()
{
CloudStorageAccount storageAccount;
public ATSHelper(CloudStorageAccount storageAccount)
{
this.storageAccount = storageAccount;
}
public async Task<IEnumerable<T>> FetchAllEntities(string tableName)
{
List<T> allEntities = new List<T>();
CloudTable table = storageAccount.CreateCloudTableClient().GetTableReference(tableName);
TableContinuationToken contToken = new TableContinuationToken();
TableQuery query = new TableQuery();
CancellationToken cancelToken = new CancellationToken();
do
{
var qryResp = await table.ExecuteQuerySegmentedAsync<T>(query, ???? EntityResolver ???? ,contToken, cancelToken);
contToken = qryResp.ContinuationToken;
allEntities.AddRange(qryResp.Results);
}
while (contToken != null);
return allEntities;
}
}
Here is a nice article describing the Table Storage in deep. It also includes couple of samples for EntityResolver.
Ideal would be to have one Generic Resolver, that produces the desired result. Then you can include it in your call. I will just quote here one example from the provided article:
EntityResolver<ShapeEntity> shapeResolver = (pk, rk, ts, props, etag) =>
{
ShapeEntity resolvedEntity = null;
string shapeType = props["ShapeType"].StringValue;
if (shapeType == "Rectangle") { resolvedEntity = new RectangleEntity(); }
else if (shapeType == "Ellipse") { resolvedEntity = new EllipseEntity(); }
else if (shapeType == "Line") { resolvedEntity = new LineEntity(); }
// Potentially throw here if an unknown shape is detected
resolvedEntity.PartitionKey = pk;
resolvedEntity.RowKey = rk;
resolvedEntity.Timestamp = ts;
resolvedEntity.ETag = etag;
resolvedEntity.ReadEntity(props, null);
return resolvedEntity;
};
currentSegment = await drawingTable.ExecuteQuerySegmentedAsync(drawingQuery, shapeResolver, currentSegment != null ? currentSegment.ContinuationToken : null);
Read the full article to better understand the deal with resolvers.