Unexpected behaviour of ILoggerFactory in EF Core - entity-framework

I need to add a logger for a specifc dbContext. For example I have the next code:
var dbContextOptionsBuilder1 = new DbContextOptionsBuilder();
dbContextOptionsBuilder1.UseSqlServer("Data Source=localhost;Initial Catalog=DataBase;Integrated Security=True");
var dbContext1 = new DbContext(dbContextOptionsBuilder1.Options);
var loggerFactory1 = dbContext1.GetService<ILoggerFactory>();
loggerFactory1.AddProvider(new CustomLoggerProvider());
var dbContextOptionsBuilder2 = new DbContextOptionsBuilder();
dbContextOptionsBuilder2.UseSqlServer("Data Source=localhost;Initial Catalog=DataBase;Integrated Security=True");
var dbContext2 = new DbContext(dbContextOptionsBuilder2.Options);
var loggerFactory2 = dbContext2.GetService<ILoggerFactory>();
If I expand non-public members of loggerFactory1 I will see my CustomLoggerProvider that I added (_providerRegistrations = Count = 1). But If I expand non-public members of loggerFactory2 I will see the same CustomLoggerProvider (_providerRegistrations = Count = 1) although I didn't add it to dbContext2.
Also I got another unexpected behaviour in the next code:
public class MyDbContext : DbContext
{
private readonly IDbService dbService;
public MyDbContext(IDbService dbService, DbContextOptions options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
}
}
var dbContextOptionsBuilder1 = new DbContextOptionsBuilder();
dbContextOptionsBuilder1.UseSqlServer("Data Source=localhost;Initial Catalog=DataBase;Integrated Security=True");
var dbContext1 = new DbContext(dbContextOptionsBuilder1.Options);
var loggerFactory1 = dbContext1.GetService<ILoggerFactory>();
loggerFactory1.AddProvider(new CustomLoggerProvider());
var dbContextOptionsBuilder2 = new DbContextOptionsBuilder();
dbContextOptionsBuilder2.UseSqlServer("Data Source=localhost;Initial Catalog=DataBase;Integrated Security=True");
var dbContext2 = new DbContext(dbContextOptionsBuilder2.Options);
var loggerFactory2 = dbContext2.GetService<ILoggerFactory>();
var dbContextOptionsBuilder3 = new DbContextOptionsBuilder();
dbContextOptionsBuilder3.UseSqlServer("Data Source=localhost;Initial Catalog=DataBase;Integrated Security=True");
var dbContext3 = new MyDbContext(new DbService(), dbContextOptionsBuilder3.Options);
var loggerFactory3 = dbContext3.GetService<ILoggerFactory>();
loggerFactory3.AddProvider(new CustomLoggerProvider());
var dbContextOptionsBuilder4 = new DbContextOptionsBuilder();
dbContextOptionsBuilder4.UseSqlServer("Data Source=localhost;Initial Catalog=DataBase;Integrated Security=True");
var dbContext4 = new MyDbContext(new DbService(), dbContextOptionsBuilder4.Options);
var loggerFactory4 = dbContext4.GetService<ILoggerFactory>();
In this case I got 1 CustomLoggerProvider in dbContext3 (_providerRegistrations = Count = 1) and the same logger in dbContext4 (_providerRegistrations = Count = 1). So there is no relationship between dbContext1, dbContext2 and dbContext3, dbContext4.
So if I add one more CustomLoggerProvider to dbContext1 I will get the next result:
dbContext1: 2 CustomLoggerProvider (_providerRegistrations = Count = 2)
dbContext2: 2 CustomLoggerProvider (_providerRegistrations = Count = 2)
dbContext3: 1 CustomLoggerProvider (_providerRegistrations = Count = 1)
dbContext4: 1 CustomLoggerProvider (_providerRegistrations = Count = 1)
What is the right way to work with ILoggerFactory?

Related

Azure Search CreateIndexAsync fails with CamelCase field names FieldBuilder

Azure Search V11
I can't get this to work. But with the standard FieldBuilder the index is created.
private static async Task CreateIndexAsync(SearchIndexClient indexClient, string indexName, Type type)
{
var builder = new FieldBuilder
{
Serializer = new JsonObjectSerializer(new JsonSerializerOptions {PropertyNamingPolicy = new CamelCaseNamingPolicy()})
};
var searchFields = builder.Build(type).ToArray();
var definition = new SearchIndex(indexName, searchFields);
await indexClient.CreateIndexAsync(definition);
}
`
public class CamelCaseNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
return char.ToLower(name[0]) + name.Substring(1);
}
}
See our sample for FieldBuilder. Basically, you must use a naming policy for both FieldBuilder and the SearchClient:
var clientOptions = new SearchClientOptions
{
Serializer = new JsonObjectSerializer(
new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
}),
};
var builder = new FieldBuilder
{
Serializer = clientOptions.Serializer,
};
var index = new SearchIndex("name")
{
Fields = builder.Build(type),
};
var indexClient = new SearchIndexClient(uri, clientOptions);
await indexClient.CreateIndexAsync(index);
await Task.DelayAsync(5000); // can take a little while
var searchClient = new SearchClient(uri, clientOptions);
var response = await searchClient.SearchAsync("whatever");
While this sample works (our sample code comes from oft-executed tests), if you have further troubles, please be sure to post the exact exception message you are getting.

List all project iterations using Microsoft.VisualStudio.Services.Client

Using Microsoft.VisualStudio.Services.Client how can I list all available iterations in my project?
I can connect happily to my VSO instance but I have no idea where to go from there.
VssConnection connection = new VssConnection(_collectionUri, _credentials);
ProjectHttpClient projClient = connection.GetClientAsync<ProjectHttpClient>().Result;
Refer to this code to get iterations:
var connection = new VssConnection(u, c);
var workItemTracking = connection.GetClient<WorkItemTrackingHttpClient>();
Microsoft.TeamFoundation.Core.WebApi.ProjectHttpClient projClient = connection.GetClientAsync<Microsoft.TeamFoundation.Core.WebApi.ProjectHttpClient>().Result;
var projects= projClient.GetProjects().Result;
foreach(var p in projects)
{
var iteration = workItemTracking.GetClassificationNodeAsync(project: p.Name, structureGroup: Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models.TreeStructureGroup.Iterations, depth: 5).Result;
GetIterations(iteration);
}
static void GetIterations(Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models.WorkItemClassificationNode currentIteration)
{
Console.WriteLine(currentIteration.Name);
if(currentIteration.Children!=null)
{
foreach (var ci in currentIteration.Children)
{
GetIterations(ci);
}
}
}

not able to save documents in mongodb c# with .Net driver 2.0

I want to save the document in a collection my method is as below but it is not saving at all.
internal static void InitializeDb()
{
var db = GetConnection();
var collection = db.GetCollection<BsonDocument>("locations");
var locations = new List<BsonDocument>();
var json = JObject.Parse(File.ReadAllText(#"..\..\test_files\TestData.json"));
foreach (var d in json["locations"])
{
using (var jsonReader = new JsonReader(d.ToString()))
{
var context = BsonDeserializationContext.CreateRoot(jsonReader);
var document = collection.DocumentSerializer.Deserialize(context);
locations.Add(document);
}
}
collection.InsertManyAsync(locations);
}
If I made async and await then it runs lately, I need to run this first and then only test the data.
For future reference, wait() at end of async method work like synchronously
internal static void InitializeDb()
{
var db = GetConnection();
var collection = db.GetCollection<BsonDocument>("locations");
var locations = new List<BsonDocument>();
var json = JObject.Parse(File.ReadAllText(#"..\..\test_files\TestData.json"));
foreach (var d in json["locations"])
{
using (var jsonReader = new JsonReader(d.ToString()))
{
var context = BsonDeserializationContext.CreateRoot(jsonReader);
var document = collection.DocumentSerializer.Deserialize(context);
locations.Add(document);
}
}
collection.InsertManyAsync(locations).wait();
}

Entity Framework Original Value not as expected

In the following code I expect the Original Value to be different to the new value that I have set.
Why does my test fail? I am using EF 6.1.0
The Original Value is being incorrectly set to the new value.
[TestMethod]
public void CheckOriginalAndNew()
{
var dbContext = new ProjectContext();
var proj = dbContext.Projects.Find( 1);
proj.Description = Guid.NewGuid().ToString();
DbSet<Project> dbSet = dbContext.Set<Project>();
dbSet.Add(proj);
foreach (var entry in dbContext.ChangeTracker.Entries())
{
entry.State = System.Data.Entity.EntityState.Modified;
}
ObjectContext objectContex = ((IObjectContextAdapter)dbContext).ObjectContext;
objectContex.DetectChanges();
var entries =
objectContex.ObjectStateManager.GetObjectStateEntries(System.Data.Entity.EntityState.Modified);
foreach (ObjectStateEntry entry in entries.Where(e => e.Entity is LoggedEntity && !e.IsRelationship))
{
for (int i = 0; i < entry.CurrentValues.FieldCount; i++)
{
string fieldName = entry.CurrentValues.DataRecordInfo.FieldMetadata[i].FieldType.Name;
int ordinal = entry.OriginalValues.GetOrdinal(fieldName);
if (fieldName == "Description")
{
object newValue = entry.CurrentValues[ordinal];
object oldValue = entry.OriginalValues[ordinal];
Assert.AreNotEqual(newValue, oldValue); // fails! Why?
}
}
}
}
The reason the original value matches the current value is that the entry has been added instead of modified.
Instead of
DbSet<Project> dbSet = dbContext.Set<Project>();
dbSet.Add(proj);
I should have used
dbContext.Entry(proj).State = System.Data.Entity.EntityState.Modified;

Get only a specified field in MongoDB with C#

first time i'm using MongoDB.
I have read this example:
SELECT a,b FROM users WHERE age=33
db.users.find({age:33}, {a:1,b:1})
But I can't translate it into C#. Can anyone help me?
I have translated your query below using the new C# driver (2.2)
var mongoClient = new MongoClient(""mongodb://127.0.0.1:27017"");
var database = mongoClient.GetDatabase("databaseName");
IMongoCollection<Users> _collection = database.GetCollection<Users>("Users");
var condition = Builders<Users>.Filter.Eq(p => p.age, 33);
var fields = Builders<Users>.Projection.Include(p => p.a).Include(p => p.b);
var results= _collection.Find(condition).Project<Users>(fields).ToList().AsQueryable();
You can do it using SetFields method of MongoCursor class, below full example:
var server = MongoServer.Create(connectionString);
var db = _server.GetDatabase("dbName");
var users = db.GetCollection("users");
var cursor = users.FindAs<DocType>(Query.EQ("age", 33));
cursor.SetFields(Fields.Include("a", "b"));
var items = cursor.ToList();
you can use anonymous class
public class User
{
public int age;
public string a;
public string b;
}
var collection = db.GetCollection<User>("Users");
var results = collection.Find(Builders<User>.Filter.Eq(user => user.age, 33))
.Project(u => new { u.a, u.b }).ToList();
//create user class
//(not sure how your class looks like)
public class User
{
public int age;
public string a;
public string b;
}
//then you can use LINQ easily
var server = MongoServer.Create(connectionString);
var db = server.GetDatabase("dbName");
var usersCollection = db.GetCollection<User>("users");
var filteredCollection = usersCollection.AsQueryable().Where(x=> x.age < 33).Where(x=> x.a != null).Contains(x=> x.b != null);