I am new in Redis cache implementation and got in simple example with getstring from Redis Cache which is working fine. But Same time I didnt get any idea about Set and get list values through Redis.
I have Using Provider and Repository. Please help me how to further proceed...
public List<Article> GetArticleListBySectionName(string sectionName, int RegionId, int Count, int CacheTime, string cacheKey, bool cacheEnable = false, string expiryInMinutes = "NoExpiry")
{
{
cacheKey = GetCacheKey(cacheKey, Convert.ToString(sectionName));
List<Article> _article = _cacheProxy.Get<List<Article>>(cacheKey);
if (_article != null)
{
_article = _articleRepositary.GetArticleListBySectionName(sectionName, RegionId, Count, CacheTime);
_cacheProxy.Store<List<Article>>(_article, cacheKey, expiryInMinutes);
}
return _article;
}
}
Here _cacheProxy.Get and _cacheProxy.Store getting null values..While executing this, I ll getting error page
Inject the dependencies
Add the below line in WebApiConfig
config.DependencyResolver = new UnityResolver(Bootstrapper.Initialise(DIContainer.Initialise()));
Add the Redis Endpoint that is 127.0.0.1:6379
Related
Documentation and examples online about compiled async queries are kinda sparse, so I might as well ask for guidance here.
Let's say I have a repository pattern method like this to query all entries in a table:
public async Task<List<ProgramSchedule>> GetAllProgramsScheduledList()
{
using (var context = new MyDataContext(_dbOptions))
{
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
return await context.ProgramsScheduledLists.ToListAsync();
}
}
This works fine.
Now I want to do the same, but with an async compiled query.
One way I managed to get it to compile is with this syntax:
static readonly Func<MyDataContext, Task<List<ProgramSchedule>>> GetAllProgramsScheduledListQuery;
static ProgramsScheduledListRepository()
{
GetAllProgramsScheduledListQuery = EF.CompileAsyncQuery<MyDataContext, List<ProgramSchedule>>(t => t.ProgramsScheduledLists.ToList());
}
public async Task<List<ProgramSchedule>> GetAllProgramsScheduledList()
{
using (var context = new MyDataContext(_dbOptions))
{
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
return await GetAllProgramsScheduledListQuery(context);
}
}
But then on runtime this exception get thrown:
System.ArgumentException: Expression of type 'System.Collections.Generic.List`1[Model.Scheduling.ProgramSchedule]' cannot be used for return type 'System.Threading.Tasks.Task`1[System.Collections.Generic.List`1[Model.Scheduling.ProgramSchedule]]'
The weird part is that if I use any other operator (for example SingleOrDefault), it works fine. It only have problem returning List.
Why?
EF.CompileAsync for set of records, returns IAsyncEnumrable<T>. To get List from such query you have to enumerate IAsyncEnumrable and fill List,
private static Func<MyDataContext, IAsyncEnumerable<ProgramSchedule>> compiledQuery =
EF.CompileAsyncQuery((MyDataContext ctx) =>
ctx.ProgramsScheduledLists);
public static async Task<List<ProgramSchedule>> GetAllProgramsScheduledList(CancellationToken ct = default)
{
using (var context = new MyDataContext(_dbOptions))
{
context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
var result = new List<ProgramSchedule>();
await foreach (var s in compiledQuery(context).WithCancellation(ct))
{
result.Add(s);
}
return result;
}
}
I have index with 17364 documents in elasticsearch.
$curl http://localhost:9200/performance/_count
{"count":17364,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0}}
Spring data repository,
public interface TestRepository extends ElasticsearchRepository<Transaction, String> {
}
Fetch all documents page by page and print:
public void testReport() {
int page = 0, pageSize = 1000;
Pageable of = PageRequest.of(page, pageSize);
Page<Transaction> all = testRepository.findAll(of);
int numberOfPages = all.getTotalPages();
log.info("All pages: {}, {}", numberOfPages, all.getTotalElements());
do {
log.info("Current page: {}, {}", of.getPageNumber(), of.getPageSize());
for (Transaction txn : all) {
log.info(mapper.writeValueAsString(txn));
}
} while ((of = of.next()) != null && (transactionRepository.findAll(of)) != null);
}
This code is returning only 10000 documents although the index has 17364 documents. Could you please help me to find why this is happening.
ElasticSearch Version: 7.9
spring-boot-starter-parent: 2.3.2.RELEASE
I see two options:
A. Since you have only 17364 documents, you could increase the index.max_result_window setting in your index to (e.g.) 20000, so that you can paginate till the end:
PUT performance/_settings
{
"index.max_result_window": 20000
}
B. If you have a bigger index and/or increasing the index.max_result_window limit is not an option for any reason, then you need to leverage the Scroll API. Spring Data ES supports two ways for doing that.
The first method involves leveraging the ElasticsearchTemplate.searchForStream() method which internally uses the Scroll API
SearchHitsIterator<Transaction> stream = elasticsearchTemplate.searchForStream(searchQuery, Transaction.class, "performance");
The second method is a bit more low-level. You need to modify your repository definition with a method that returns a Stream:
public interface TestRepository extends ElasticsearchRepository<Transaction, String> {
Stream<Transaction> findScrollAll();
}
And then implement that method with ElasticsearchTemplate. searchScrollStart() and ElasticsearchTemplate. searchScrollContinue()
Addition:
3rd option:
Just define a method
Stream<Searchhit<Transaction>> searchBy()
in your Testrepository. Or with just the return type Stream<Transaction>.
I am trying to test a simple NHibernate-based auditing mechanism that stores one row per changed property into a changelog table. What it actually does, is perform the actual insert statement as expected and perform the audit logging twice.
So, this is what I do:
string connectionString = #"Data Source=.\SQLEXPRESS;Initial Catalog=audittest;Integrated Security=SSPI;";
FluentConfiguration config = Fluently.Configure().Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c => c.Is(connectionString)).ShowSql())
.Mappings(x => x.FluentMappings.Add<Class1ClassMap>())
.Mappings(x => x.FluentMappings.Add<ChangeLogMap>())
.ExposeConfiguration(cfg =>
{
NHibernateAuditListener listener = new NHibernateAuditListener();
cfg.AppendListeners(ListenerType.PostInsert, new[] { listener });
});
ISessionFactory sf = config.BuildSessionFactory();
ISession session = sf.OpenSession();
using (ITransaction tr = session.BeginTransaction())
{
session.Save(new Class1()
{
FirstName="Peter",
LastName="Pan",
Id=100
});
tr.Commit();
}
EDIT:
Altered the logging code to something simple to see the failure:
public void OnPostInsert(PostInsertEvent #event)
{
if (#event.Entity is IAuditable)
{
Console.WriteLine("----write audit----");
for (int index = 0; index < #event.State.Length; index++)
Console.WriteLine("----store changes of property {0}----",
#event.Persister.PropertyNames[index]);
}
}
This generates the following output:
NHibernate: INSERT INTO "Class1" (FirstName, LastName, Id) VALUES (#p0, #p1, #p2); #p0 = 'Peter' [Type: String (0)], #p1 = 'Pan' [Type: String (0)], #p2 = 1 [Type: Int64 (0)]
----write audit----
----store changes of property FirstName----
----store changes of property LastName----
----write audit----
----store changes of property FirstName----
----store changes of property LastName----
As you see, it's not the EventHandler code that's erroneous, but the framework calling it that behaves unexpectedly (calling the OnPostInsert method twice). Any ideas why this is happening?
SAMPLE PROJECT DOWNLOAD
Okay everybody, the problem exists in the detail of the handling within the programm. You are building up a FluentConfiguration-instance which on the fly creates the the basic NHibernate configuration.
This is done on the call of these 2 lines (variable config is of type FluentConfiguration):
new SchemaExport(config.BuildConfiguration()).Create(true, true);
and
ISessionFactory sf = config.BuildSessionFactory();
The FluentConfiguration caches the first created instance and reuses it for creating the new instance for the ISessionFactory-instance. On both calls the ExposeConfiguration of FluentConfiguration instance is called. So there are 2 instances of the NHibernateAuditListener within the session that is persisting the data.
Try it like this:
string connectionString = #"Data Source=.\SQLEXPRESS;Initial Catalog=audittest;Integrated Security=SSPI;";
var config = Fluently.Configure().Database(MsSqlConfiguration.MsSql2008
.ConnectionString(c => c.Is(connectionString)).ShowSql())
.Mappings(x => x.FluentMappings.Add<Class1ClassMap>())
.Mappings(x => x.FluentMappings.Add<ChangeLogMap>())
.ExposeConfiguration(cfg =>
{
NHibernateAuditListener listener = new NHibernateAuditListener();
cfg.AppendListeners(ListenerType.PostInsert, new[] { listener });
})
.BuildConfiguration();
new SchemaExport(config).Create(true, true);
Console.WriteLine("----------------------------------------------");
ISessionFactory sf = config.BuildSessionFactory();
ISession session = sf.OpenSession();
using (ITransaction tr = session.BeginTransaction())
{
session.Save(new Class1()
{
FirstName="Peter",
LastName="Pan",
Id=100
});
tr.Commit();
}
Within config you have now the real NHibernate Configuration instance, with only one Listener registered.
Got it?!
Currently I'm developing an OAuth2 authorization server using DotNetOpenAuth CTP version. My authorization server is in asp.net MVC3, and it's based on the sample provided by the library. Everything works fine until the app reaches the point where the user authorizes the consumer client.
There's an action inside my OAuth controller which takes care of the authorization process, and is very similar to the equivalent action in the sample:
[Authorize, HttpPost, ValidateAntiForgeryToken]
public ActionResult AuthorizeResponse(bool isApproved)
{
var pendingRequest = this.authorizationServer.ReadAuthorizationRequest();
if (pendingRequest == null)
{
throw new HttpException((int)HttpStatusCode.BadRequest, "Missing authorization request.");
}
IDirectedProtocolMessage response;
if (isApproved)
{
var client = MvcApplication.DataContext.Clients.First(c => c.ClientIdentifier == pendingRequest.ClientIdentifier);
client.ClientAuthorizations.Add(
new ClientAuthorization
{
Scope = OAuthUtilities.JoinScopes(pendingRequest.Scope),
User = MvcApplication.LoggedInUser,
CreatedOn = DateTime.UtcNow,
});
MvcApplication.DataContext.SaveChanges();
response = this.authorizationServer.PrepareApproveAuthorizationRequest(pendingRequest, User.Identity.Name);
}
else
{
response = this.authorizationServer.PrepareRejectAuthorizationRequest(pendingRequest);
}
return this.authorizationServer.Channel.PrepareResponse(response).AsActionResult();
}
Everytime the program reaches this line:
this.authorizationServer.Channel.PrepareResponse(response).AsActionResult();
The system throws an exception which I have researched with no success. The exception is the following:
Only parameterless constructors and initializers are supported in LINQ to Entities.
The stack trace: http://pastebin.com/TibCax2t
The only thing I've done differently from the sample is that I used entity framework's code first approach, an I think the sample was done using a designer which autogenerated the entities.
Thank you in advance.
If you started from the example, the problem Andrew is talking about stays in DatabaseKeyNonceStore.cs. The exception is raised by one on these two methods:
public CryptoKey GetKey(string bucket, string handle) {
// It is critical that this lookup be case-sensitive, which can only be configured at the database.
var matches = from key in MvcApplication.DataContext.SymmetricCryptoKeys
where key.Bucket == bucket && key.Handle == handle
select new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc());
return matches.FirstOrDefault();
}
public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket) {
return from key in MvcApplication.DataContext.SymmetricCryptoKeys
where key.Bucket == bucket
orderby key.ExpiresUtc descending
select new KeyValuePair<string, CryptoKey>(key.Handle, new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc()));
}
I've resolved moving initializations outside of the query:
public CryptoKey GetKey(string bucket, string handle) {
// It is critical that this lookup be case-sensitive, which can only be configured at the database.
var matches = from key in db.SymmetricCryptoKeys
where key.Bucket == bucket && key.Handle == handle
select key;
var match = matches.FirstOrDefault();
CryptoKey ck = new CryptoKey(match.Secret, match.ExpiresUtc.AsUtc());
return ck;
}
public IEnumerable<KeyValuePair<string, CryptoKey>> GetKeys(string bucket) {
var matches = from key in db.SymmetricCryptoKeys
where key.Bucket == bucket
orderby key.ExpiresUtc descending
select key;
List<KeyValuePair<string, CryptoKey>> en = new List<KeyValuePair<string, CryptoKey>>();
foreach (var key in matches)
en.Add(new KeyValuePair<string, CryptoKey>(key.Handle, new CryptoKey(key.Secret, key.ExpiresUtc.AsUtc())));
return en.AsEnumerable<KeyValuePair<string,CryptoKey>>();
}
I'm not sure that this is the best way, but it works!
It looks like your ICryptoKeyStore implementation may be attempting to store CryptoKey directly, but it's not a class that is compatible with the Entity framework (due to not have a public default constructor). Instead, define your own entity class for storing the data in CryptoKey and your ICryptoKeyStore is responsible to transition between the two data types for persistence and retrieval.
I've made a utility method to get schema from a db table. In this case Oracle 11 db.
public static DataTable GetColumnsSchemaTable(DbConnection cnctn, string tableName)
{
DataTable schemaTable;
string[] restrictions = new string[3] { null, tableName, null };
schemaTable = cnctn.GetSchema("Columns", restrictions);
/* table name is case sensitive and in XXXX db table names are UPPER */
if (schemaTable.Rows.Count == 0)
{
restrictions = new string[3] { null, tableName.ToUpper(), null };
schemaTable = cnctn.GetSchema("Columns", restrictions);
}
return schemaTable;
}
This works fine when the cnctn is created with System.Data.OracleClient provider factory. When it's created with System.Data.OleDb provider factory the table has no rows. I have an other utility method to get connection strings:
public static string GetDbConnectionString(DbConnection cnnctn, string provider, string server, string dbName, string user, string pwd)
{
if (cnnctn is OleDbConnection)
{
string usedProvider;
if (provider == null)
usedProvider = "msdaora";
else
usedProvider = provider;
return string.Format("Provider={0};Data Source={1};User Id={2};Password={3};",
usedProvider, dbName, user, pwd);
}
else if (cnnctn is System.Data.OracleClient.OracleConnection)
{
return string.Format("Data Source={0};User Id={1};Password={2};",
dbName, user, pwd);
}
else if (cnnctn is Oracle.DataAccess.Client.OracleConnection)
{
return string.Format("Data Source={0};User Id={1};Password={2};",
dbName, user, pwd);
}
else if (cnnctn is SqlConnection)
{
return string.Format("Data Source={0}; Initial Catalog={1}; User Id={2}; Password={3};",
server, dbName, user, pwd);
}
return string.Empty;
}
and the db connection works (i'm deleting rows before trying to get schema). All help will be appreciated.
Thanks & Best Regards - Matti
Ok. I sorted it out. I made this code long time ago only for now deprecated OracleClient and left the possibility to use other connections / provider factories. I didn't remember anymore that the restrictions vary from connection to connection. So the correct usage is:
string[] restrictions = new string[4] { null, null, tableName, null };
for OleDbConnection.