I've been following the official documentation here:
https://learn.microsoft.com/en-us/azure/cosmos-db/sql-api-get-started#Query
But I can't figure out how to correctly use a LINQ expression instead on an SQL string. I experimented with GetItemLinqQueryable, but I don't know if is the right way to use it. Also is not async.
var db = Client.GetDatabase(databaseId);
var container = db.GetContainer(containerId);
var q = container.GetItemLinqQueryable<Person>();
var result = q.Where(p => p.Name == "Name").ToList();
Is this the right way to use LINQ with Cosmos v3, and how to make it async?
You would use ToFeedIterator() and FeedIterator<T>.ReadNextAsync().
var db = Client.GetDatabase(databaseId);
var container = db.GetContainer(containerId);
var q = container.GetItemLinqQueryable<Person>();
var iterator = q.Where(p => p.Name == "Name").ToFeedIterator();
var results = await iterator.ReadNextAsync();
If your application follows a layered architecture and you'd like to give your domain layer full control over the query then it's possible to wrap cosmos IQueryable<Person> with a custom IQueryProvider that implements IAsyncEnumerable e.g.
By doing that you can hide the implementation details of asynchronously iterating over the result from your domain layer.
Persistence layer
public class PersonRepository
{
public IQueryable<Person> Persons => _cosmosContainer.GetItemLinqQueryable<Person>().ToCosmosAsyncQueryable();
}
Domain layer
var persons = await _personRepository.Persons
.Where(p => p.Name == "Name")
.AsAsyncQueryable()
.ToListAsync(cancellationToken);
ToListAsync is available from System.Linq.Async that can be referenced from your domain layer
Domain layer extensions
public static IAsyncEnumerable<T> AsAsyncQueryable<T>(this IQueryable<T> queryable)
{
return (IAsyncEnumerable<T>)queryable;
}
Persistence layer extensions
internal static class CosmosAsyncQueryableExtensions
{
internal static IQueryable<T> ToCosmosAsyncQueryable<T>(this IOrderedQueryable<T> source)
{
return new CosmosAsyncQueryable<T>(source);
}
}
internal class CosmosAsyncQueryable<TResult> : IEnumerable<TResult>, IQueryable<TResult>, IAsyncEnumerable<TResult>
{
private readonly IQueryable<TResult> _queryable;
public CosmosAsyncQueryable(IQueryable<TResult> queryable)
{
_queryable = queryable;
Provider = new CosmosAsyncQueryableProvider(queryable.Provider);
}
public Type ElementType => typeof(TResult);
public Expression Expression => _queryable.Expression;
public IQueryProvider Provider { get; }
public IEnumerator<TResult> GetEnumerator() => _queryable.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => _queryable.GetEnumerator();
public async IAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
var iterator = _queryable.ToFeedIterator();
while (iterator.HasMoreResults)
{
foreach (var item in await iterator.ReadNextAsync(cancellationToken))
{
yield return item;
}
}
}
}
internal class CosmosAsyncQueryableProvider : IQueryProvider
{
private readonly IQueryProvider _provider;
public CosmosAsyncQueryableProvider(IQueryProvider provider) => _provider = provider;
public IQueryable<TElement> CreateQuery<TElement>(Expression expression) =>
new CosmosAsyncQueryable<TElement>(_provider.CreateQuery<TElement>(expression));
public IQueryable CreateQuery(Expression expression) => CreateQuery<object>(expression);
public object Execute(Expression expression) => _provider.Execute(expression);
public TResult Execute<TResult>(Expression expression) => _provider.Execute<TResult>(expression);
}
Related
I have an middleware which checks that some parameters in request's header are correct, and I check that there is one entity in db associated with one parameter from header (e.g foo).
But after this I need to get that entity again for getting some properties (e.g fooEntity.bar)
Is there way to set some object like { entity : fooEntity} in middleware to di and resolve that object in services?
I want to reduce db calls
this is example of app
public class SomeMiddleware
{
private readonly RequestDelegate _next;
private readonly ISomeService _someService;
public SomeMiddleware(RequestDelegate next, ISomeService someService)
{
_next = next;
_someService = someService;
}
public async Task InvokeAsync(HttpContext context)
{
var foo = RequestHeaderExtractor.GetValue(context.Request, Constants.FooName); // just getting value from header
var baz = RequestHeaderExtractor.GetValue(context.Request, Constants.BazName);
await _someService.Assert(foo);
await _next(context);
}
}
public class SomeService : ISomeService
{
private readonly IServiceScopeFactory _scopeFactory;
public AuthenticationService(IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
public async Task Assert(string foo)
{
using var scope = _scopeFactory.CreateScope();
var context = scope.ServiceProvider.GetService<Context>();
var fooEntity = await context
.Foo
.Include(x => x.Bar)
.FirstOrDefaultAsync(x => x.Foo == foo);
if (fooEntity?.Bar == null || string.IsNullOrEmpty(fooEntity.Bar.Something))
{
throw new Exception("111 alarm");
}
}
}
// this is fooEntity.Bar.Something consumer
public class SomeHttpClient : ISomeHttpClient
{
private readonly HttpClient _client;
public SomeHttpClient(IHttpClientFactory httpClientFactory, IRequestInformationService requestInformationService)
{
_client = httpClientFactory.CreateClient();
var something = requestInformationService.GetSomethingFromBar(); // getting FooEntity.Bar.Something
var baseUri = new Uri(something);
_client.BaseAddress = baseUri;
// others setting
}
}
public class RequestInformationService : IRequestInformationService
{
private readonly HttpContext _httpContext;
private readonly DataContext _dataContext;
public RequestInformationService(IHttpContextAccessor httpContextAccessor, DataContext dataContext)
{
_dataContext = dataContext;
_httpContext = httpContextAccessor.HttpContext;
}
public Uri GetSomethingFromBar()
{
//do the same operation like in middleware
var foo = RequestHeaderExtractor.GetValue(_httpContext.Request, Constants.FooName);
var fooEntity = _dataContext
.Foo
.Include(x => x.Bar)
.FirstOrDefault(x => x.Foo == foo);
return fooEntity.Bar.Something;
}
}```
I am having one frustrating time attempting to follow the Couchbase documentation (which is horribly outdated and the examples just do not even compile).
I already have several other persistence stacks following this same pattern. I would like to migrate to Couchbase from CosmosDb and I simply cannot figure out how to implement this in a generic pattern. FYI, I am not here to debate the move from Cosmos to Couchbase, so the let please leave that topic alone.
I have already done this for Mongo, Dynamo, PostresSql, MsftSql, Cosmos Document, Cosmos SQL, and Cosmos Table.
Nuget Packages:
Couchbase.Lite # 2.7.1
CouchbaseNetClient # 3.0.1
The IPlatformRepository interface, used by all repositories in the system
Task<T> CreateAsync(T data);
Task<T> ReadAsync(Guid id);
Task<bool> UpdateAsync(T data);
Task<bool> DeleteAsync(Guid id);
Task<IEnumerable<T>> AllAsync();
Task<IEnumerable<T>> QueryAsync(Expression<Func<T, bool>> predicate = null);
Here is the PoC code that I have in my Couchbase provider, but I am stuck at trying to figure out how to do the AllAsync() and QueryAsync() functions (commented out QueryAsync() is from the CosmosDocument provider I have. I have not started on that one yet. I started with the AllAsync() to just retrieve the documents.
public class CouchbaseRepository<T> : IPlatformRepository<T>
where T: DomainAggregate
{
private readonly string collectionName;
private readonly CouchbaseSettings couchbaseSettings;
private ICluster cluster;
private IBucket bucket;
private ICollection<T> collection;
private ICouchbaseCollection cbc;
public CouchbaseRepository(CouchbaseSettings settings)
{
Inflector.Inflector.SetDefaultCultureFunc = () => new CultureInfo("en");
collectionName = typeof(T).Name.Pluralize().Uncapitalize();
}
public async Task<T> ReadAsync(Guid id)
{
var result = await bucket.Collection(collectionName).GetAsync(id.ToString());
return result.ContentAs<T>();
}
public async Task<IEnumerable<T>> QueryAsync(Expression<Func<T, bool>> predicate)
{
// var results = new List<T>();
//
// var query = client.CreateDocumentQuery<T>(
// UriFactory.CreateDocumentCollectionUri(
// databaseId,
// collectionId),
// new FeedOptions
// {
// MaxItemCount = -1,
// EnableCrossPartitionQuery = true
// });
//
// predicate = null;
// var conditionalQuery = predicate == null
// ? query
// : query.Where(predicate);
//
// var documentQuery = conditionalQuery.AsDocumentQuery();
//
// while (documentQuery.HasMoreResults)
// {
// results.AddRange(await documentQuery.ExecuteNextAsync<T>());
// }
//
// return results;
}
public async Task<IEnumerable<T>> AllAsync()
{
using (var cluseter = new Cluster())
{
}
}
public async Task<T> CreateAsync(T item)
{
var result = await bucket.Collection(collectionName).InsertAsync(item.Id.ToString(), item);
return item;
}
public async Task<bool> UpdateAsync(T item)
{
}
public async Task<bool> DeleteAsync(Guid id)
{
}
private async Task EstablishConnection()
{
cluster = await Cluster.ConnectAsync(couchbaseSettings.Endpoint, couchbaseSettings.User, couchbaseSettings.Password);
bucket = await cluster.BucketAsync(couchbaseSettings.Bucket);
}
}
I have an asp.net webapi hosted using OWin and I use ninject for DI. Here is how I inject DbContext:
kernel.Bind<IAuthRepository>().To<AuthRepository>();
kernel.Bind<AuthDbContext>().ToSelf().InRequestScope();
I have a repository class that I use the context as below:
private AuthDbContext _ctx { get; set; }
public AuthRepository(AuthDbContext ctx)
{
_ctx = ctx;
}
There is this method in repository that I call to change some data:
var res = await _ctx
.Clients
.FirstOrDefaultAsync(clientEntity => clientEntity.UserRef.Id == p);
//do the modification
_ctx.Entry(res).State = EntityState.Modified;
_ctx.SaveChanges();
return res;
It saves the data correctly in db, but after, when I call another action and get that saved entity, I see that changes are not in the context.
public async Task<Client> FindClientById(Guid clientId)
{
return await _ctx
.Clients
.FirstOrDefaultAsync(clientEntity => clientEntity.Id == clientId);
}
I have a cached repository
public interface IRepository
{
void LogWebUsage(string html);
IEnumerable<ApiKey> GetApiKeys();
ApiKey GetApiKey(Guid key);
}
public class Repository : IRepository
{
private static readonly ILog Log = LogManager.GetLogger("API.Repository");
public IDbConnectionFactory DbFactory { get; set; }
public void LogWebUsage(string request)
{
Log.Debug(request);
}
public virtual IEnumerable<ApiKey> GetApiKeys()
{
List<ApiKey> result = null;
using (var db = DbFactory.OpenDbConnection())
{
result = db.SelectParam<ApiKey>(q => q.Active);
}
return result;
}
public ApiKey GetApiKey(Guid key)
{
ApiKey result = null;
using (var db = DbFactory.OpenDbConnection())
{
result = (db.SelectParam<ApiKey>(q => q.Id == key)).FirstOrDefault();
}
return result;
}
}
public class CachedRepository : Repository
{
public ICacheClient Cache { get; set; }
public override IEnumerable<ApiKey> GetApiKeys()
{
const string cacheKey = "GetApiKeys";
var result = Cache.Get<IEnumerable<ApiKey>>(cacheKey);
if (result == null)
{
result = base.GetApiKeys();
if (result.Any())
{
Cache.Add(cacheKey, result, TimeSpan.FromMinutes(30));
}
}
return result;
}
}
And I configure it like so.
//Register any dependencies you want injected into your services
container.Register<IDbConnectionFactory>(new OrmLiteConnectionFactory(ConfigUtils.GetConnectionString("DBConnstr"), true, SqlServerOrmLiteDialectProvider.Instance));
container.Register<ICacheClient>(new MemoryCacheClient());
container.Register<IRepository>(new CachedRepository());
container.RegisterAutoWired<CachedRepository>();
So what I was hoping for is that both the IDbConnectionFactory and ICacheClient would be injected at run-time, but they are null. How to you properly account for this type of dependency graph?
Thank you,
Stephen
Updated
After googling for a couple of hours I finally found a solution that works. Constructor injection though the config.
public class CachedRepository : Repository
{
private ICacheClient Cache { get; set; }
public CachedRepository(IDbConnectionFactory dbFactory, ICacheClient cache) : base(dbFactory)
{
Cache = cache;
}
public override IEnumerable<ApiKey> GetApiKeys()
{
const string cacheKey = "GetApiKeys";
var result = Cache.Get<IEnumerable<ApiKey>>(cacheKey);
if (result == null)
{
result = base.GetApiKeys();
if (result.Any())
{
Cache.Add(cacheKey, result, TimeSpan.FromMinutes(30));
}
}
return result;
}
}
Configuration
//Register any dependencies you want injected into your services
container.Register<IDbConnectionFactory>(c => new OrmLiteConnectionFactory(ConfigUtils.GetConnectionString("DBConnstr"), true, SqlServerOrmLiteDialectProvider.Instance));
container.Register<ICacheClient>(c => new MemoryCacheClient());
container.Register<IRepository>(c => new CachedRepository(c.Resolve<IDbConnectionFactory>(), c.Resolve<ICacheClient>()));
It works, but I'd still like to know how to wire up the property injection.
Take care,
Stephen... again
The APIs for AutoWiring in ServiceStack's Funq IOC are here:
Using Generic API:
container.RegisterAutoWired<MyType>();
container.RegisterAutoWiredAs<MyType,IMyType>();
Using Run-time typed API:
container.RegisterAutoWiredType(typeof(MyType));
container.RegisterAutoWiredType(typeof(MyType),typeof(IMyType));
container.RegisterAutoWiredTypes(typeof(MyType),typeof(MyType2),typeof(MyType3));
So basically you can use any of the above APIs to auto-wire your dependencies, e.g:
container.Register<IDbConnectionFactory>(c => new
OrmLiteConnectionFactory(ConfigUtils.GetConnectionString("DBConnstr"), true,
SqlServerDialect.Provider));
container.Register<ICacheClient>(c => new MemoryCacheClient());
container.RegisterAutoWiredAs<CachedRepository,IRepository>(); //auto-wired
I've see n a lot of discussions surrounding HttpSessionState and asp.net MVC.
I'm trying to write tests for an asp.net application and wondering if it's possible to mock the HttpSessionState and if so, how?
I'm currently using Rhino Mocks and Nunit
Gilbert,
Maybe I'm too late for you. I'm using MSpec, but I think the concepts are similar. I needed to mock several components of the HttpContext in the controllers under test.
I started with these following classes to mock up the necessary (for my purposes) components in the HttpContextBase. I overrode only the necessary pieces inside the classes. Your needs will vary as to the mocks you need in the controller. It's fairly easy to add mocks as needed once you understand the pattern.
public class MockHttpContext : HttpContextBase
{
private readonly HttpRequestBase _request = new MockHttpRequest();
private readonly HttpServerUtilityBase _server = new MockHttpServerUtilityBase();
private HttpSessionStateBase _session = new MockHttpSession();
public override HttpRequestBase Request
{
get { return _request; }
}
public override HttpServerUtilityBase Server
{
get { return _server; }
}
public override HttpSessionStateBase Session
{
get { return _session; }
}
}
public class MockHttpRequest : HttpRequestBase
{
private Uri _url = new Uri("http://www.mockrequest.moc/Controller/Action");
public override Uri Url
{
get { return _url; }
}
}
public class MockHttpServerUtilityBase : HttpServerUtilityBase
{
public override string UrlEncode(string s)
{
//return base.UrlEncode(s);
return s; // Not doing anything (this is just a Mock)
}
}
public class MockHttpSession : HttpSessionStateBase
{
// Started with sample http://stackoverflow.com/questions/524457/how-do-you-mock-the-session-object-collection-using-moq
// from http://stackoverflow.com/users/81730/ronnblack
System.Collections.Generic.Dictionary<string, object> _sessionStorage = new System.Collections.Generic.Dictionary<string,object>();
public override object this[string name]
{
get { return _sessionStorage[name]; }
set { _sessionStorage[name] = value; }
}
public override void Add(string name, object value)
{
_sessionStorage[name] = value;
}
}
Here is how I setup the Controller Context to use the mocks (MSpec). This is setup for the actual tests on the contoller (the tests derive from this class)
public abstract class BlahBlahControllerContext
{
protected static BlahBlahController controller;
Establish context = () =>
{
controller = new BlahBlahController();
controller.ControllerContext = new ControllerContext()
{
Controller = controller,
RequestContext = new RequestContext(new MockHttpContext(), new RouteData()),
};
};
}
To further illustrate here is a test (Specification in MSpec world) that uses the mock session:
[Subject("ACCOUNT: Retrieve Password")]
public class retrieve_password_displays_retrieve_password2_page_on_success : BlahBlahControllerContext
{
static ActionResult result;
static RetrievePasswordModel model;
Establish context = () =>
{
model = new RetrievePasswordModel()
{
UserName = "Mike"
};
};
Because of = () =>
{
result = controller.RetrievePassword(model);
};
It should_return_a_RedirectToRouteResult = () =>
{
result.is_a_redirect_to_route_and().action_name().ShouldEqual("RetrievePassword2");
};
It session_should_contain_UN_value = () =>
{
controller.HttpContext.Session["UN"].ShouldEqual("Mike");
};
It session_should_contain_PQ_value = () =>
{
controller.HttpContext.Session["PQ"].ShouldEqual("Question");
};
}
I realize this doesn't use Rhino Mocks. I hope it illustrates the principles and readers can adopt it to their specific tools and methods.
If you need to instantiate exactly HttpSessionState for legacy code tests, you can leverage FormatterServices mechanism to get uninitialized object. To get it working it is needed to set private _container field though, like in internal constructor
Example:
var state = (HttpSessionState) System.Runtime.Serialization
.FormatterServices.GetUninitializedObject(typeof(HttpSessionState));
var containerFld = typeof(HttpSessionState).GetField(
"_container", BindingFlags.Instance | BindingFlags.NonPublic);
var itemCollection = new SessionStateItemCollection();
itemCollection["element"] = 1;
containerFld.SetValue(
state,
new HttpSessionStateContainer(
"1",
itemCollection,
new HttpStaticObjectsCollection(),
900,
true,
HttpCookieMode.UseCookies,
SessionStateMode.InProc,
false
)
);
look at the HttpSessionStateBase and HttpSessionStateWrapper classes in System.Web.Abstractions. HttpSessionStateBase is the abstract class from which HttpSessionState inherits, and HttpSessionStateWrapper is used to wrap a sealed class in an abstract class, which you can then mock in your tests.
A lot of the System.Web classes are sealed (for example, HttpSessionState), so it's a real pain to test your code when you have methods and classes that interact with them. One pattern I like to use to get around this looks like the following:
public void DoSomething(HttpSessionState state)
{
// take this HttpSeassionState and create an abstract HttpSessionStateBase
// instance
DoSomething(new HttpSessionStateWrapper(state));
}
internal void DoSomething(HttpSessionStateBase state)
{
// my actual logic for working with the session state
}
The public method is difficult to test, because HttpSessionState is sealed, and you can't mock it. However, the internal method operates on an HttpSessionStateBase instance, which you can mock. Note that I've marked it as internal because I don't want the outside world to be able to access that method. However, I do want my tests to be able to access that, so I'll modify my AssemblyInfo.cs to include something like this:
[assembly: InternalsVisibleTo("Vendor.Utilities.Tests")]
Finally, my test for this would look something like this:
[Test]
public void Test_DoSomething()
{
HttpSessionStateBase state = MockRepository.PartialMock<HttpSessionStateBase>();
state.Expect(s => ...);
MyClass.DoSomething(state);
state.VerifyAllExpectations();
}
Hope that helps. Good luck!
This is what I made up based on others contribution...
public class MockWebContext
{
public Mock<RequestContext> RoutingRequestContext { get; private set; }
public Mock<HttpContextBase> Http { get; private set; }
public Mock<HttpServerUtilityBase> Server { get; private set; }
public Mock<HttpResponseBase> Response { get; private set; }
public Mock<HttpRequestBase> Request { get; private set; }
public Mock<HttpSessionStateBase> Session { get; private set; }
public Mock<ActionExecutingContext> ActionExecuting { get; private set; }
public HttpCookieCollection Cookies { get; private set; }
private IDictionary items;
public MockWebContext()
{
RoutingRequestContext = new Mock<RequestContext>(MockBehavior.Loose);
ActionExecuting = new Mock<ActionExecutingContext>(MockBehavior.Loose);
Http = new Mock<HttpContextBase>(MockBehavior.Loose);
Server = new Mock<HttpServerUtilityBase>(MockBehavior.Loose);
Response = new Mock<HttpResponseBase>(MockBehavior.Loose);
Request = new Mock<HttpRequestBase>(MockBehavior.Loose);
Session = new Mock<HttpSessionStateBase>(MockBehavior.Loose);
Cookies = new HttpCookieCollection();
items = new Dictionary<string, object>();
RoutingRequestContext.SetupGet(c => c.HttpContext).Returns(Http.Object);
ActionExecuting.SetupGet(c => c.HttpContext).Returns(Http.Object);
Http.SetupGet(c => c.Request).Returns(Request.Object);
Http.SetupGet(c => c.Response).Returns(Response.Object);
Http.SetupGet(c => c.Server).Returns(Server.Object);
Http.SetupGet(c => c.Session).Returns(Session.Object);
Http.SetupGet(c => c.Items).Returns(items);
Request.Setup(c => c.Cookies).Returns(Cookies);
Request.Setup(c => c.RequestContext).Returns(RoutingRequestContext.Object);
Response.Setup(c => c.Cookies).Returns(Cookies);
Session.Setup(c =>
c.Add(It.IsAny<string>(), It.IsAny<object>())
).Callback((string key, object value)=> items.Add(key, value));
Session.Setup(c =>
c.Remove(It.IsAny<string>())
).Callback((string key) => items.Remove(key));
Session.Setup(c =>
c.Clear()
).Callback(() => items.Clear());
Session.Setup(c =>
c[It.IsAny<string>()]
).Returns((string key)=> items[key]);
}
}
Check out the MvcContrib project.