My contract model class
#Data
#Document(indexName = "contract",type = "contract")
public class Contract implements Serializable
{
#JsonProperty("contract_number")
#Id
#Parent(type = "p")
#Field(type = FieldType.Text,index =true)
private String contract_number;
private String startDate;
private String endDate;
private String supportTypeCode;
#Field(type = FieldType.Nested,searchAnalyzer = "true")
private List<Product> products;
My product class
#Data
public class Product implements Serializable
{
#Field(type = FieldType.Keyword)
private String baseNumber;
#Field(type = FieldType.Keyword)
private String rowId;
#Field(type = FieldType.Keyword)
private String effectiveDate;
}
Using spring data I,m trying to fetch data based on baseNumber which is present in product class.
But not able to get data.
I tried using below JPA Method but it is not working.
Optional<Contract> findByProducts_BaseNumber(String s)
I am quite confused about how to maintain a mapping between Contract and Product class.
That should be
findByProductsBaseNumber(String s);
or
findByProducts_BaseNumber(String s);
as explained in the documentation
For me below solution worked I'm using elastic 7.6 version java API.
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("products.baseNumber", baseNumber);
searchSourceBuilder.query(matchQueryBuilder);
searchSourceBuilder.from(0);
searchSourceBuilder.size(5);
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices(INDEX);
searchRequest.source(searchSourceBuilder);
SearchHits hits = null;
try
{
hits = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT).getHits();
final List<Contract> collect = Arrays.stream(hits.getHits()).map(
sourceAsMap -> objectMapper.convertValue(sourceAsMap.getSourceAsMap(), Contract.class)).collect(
Collectors.toList());
return collect.get(0);
}
catch (IOException e)
{
e.printStackTrace();
}
In dart we can execute some code when value of field is changed using something like
class Name{
String fname;
String lname;
}
class Person extends ChangeNotifier{
Name _name = Name();
set name(Name n){
notifyListeners();
_name = n;
}
get name=>_name;
}
//inside main()
Person p = Person();
p.name = Name();
I want to be able to perform similar action while setting inner fields. Such as while doing
p.name.fname ="FooBar";
But I want to be able to do it from Person class.
Because I am extending ChangeNotifier in Person class. And I want to call
notifyListeners()
that is not accessible in Name class. This is best I've come up with
Name newName = Name(p.name); //copy constructor
newName.fname = "Foo Bar";
p.name = newName;
Is there a better way?
What you can do depends on how you can constrain the API.
If Name objects are routinely being created by third-party code and passed around, and are expected to retain their identity when stored in a Person object, then here isn't much you can do. So I wouldn't design the Person object that way.
Instead I'd say that the Name object of a Person object is linked to that, and setting the name of a Person is the same as setting both name parts.
Example:
class Person {
_PersonName _name;
Person(...) : ... {
_name = _PersonName(this);
}
...
void set name(Name name) {
_name.fname = name.fname;
_name.lname = name.lname;
notifyListeners();
}
Name get name => _name;
}
class _PersonName extends Name {
final Person _owner;
_PersonName(this._owner);
void set fname(String fname) {
super.fname = fname;
_owner.notifyListeners();
}
void set lname(String lname) {
super.lname = lname;
_owner.notifyListeners();
}
}
That has the disadvantage that the extracted _PersonName is forever linked to the Person object, even if you try to write a different Name object.
Another option is to create a new _PersonName on every store a new name object, and detach the old object from the Person at that point:
class Person {
_PersonName _name = _PersonName;
Person(...) : ... {
_name = _PersonName(this, null, null);
}
void set name(Name name) {
_name.owner = null;
_name = _PersonName(this, name.fname, name.lname);
notifyListeners();
}
Name get name => _name;
}
class _PersonName extends Name {
Person _owner;
_PersonName(this._owner, String fname, String lname) {
super.fname = fname;
super.lname = lname;
}
void set fname(String fname) {
super.fname = fname;
owner?.notifyListeners();
}
void set lname(String lname) {
super.lname = lname;
owner?.notifyListeners();
}
}
This approach behaves mostly like the plain storing of name objects, except that if you do:
var p = Person();
var n = Name();
p.name = n;
print(identical(n, p.name)); // false?
you don't preserve the identity of the Name object stored into the Person object.
There is no way to do so, and also change the behavior of setting strings directly on the name using person.name.fname = ..., so something has to be sacrificed.
Below is the code from the DotNetNuke Sample module that gets a collection of items from the database that belong to a particular module. What I want is add a second parameter for it filter by. I'm guessing this has something to do with modifying the scope item.cs class but am not sure how exactly.
public IEnumerable<Item> GetItems(int moduleId)
{
IEnumerable<Item> t;
using (IDataContext ctx = DataContext.Instance())
{
var rep = ctx.GetRepository<Item>();
t = rep.Get(moduleId);
}
return t;
}
Any ideas?
Another way to do it in DAL2 is using the .Find() method. This is good if you want to query on an indexed field in your table and you don't care about caching scope:
public IEnumerable<Item> GetItemByName(int moduleId, string itemname)
{
IEnumerable<Item> t;
using (IDataContext ctx = DataContext.Instance())
{
var rep = ctx.GetRepository<Item>();
t = rep.Find("WHERE ModuleId = #0 AND ItemName LIKE #1", moduleId, itemname);
}
return t;
}
Here's some sample code from my SignalRChat module that uses DAL2 (http://signalrchat.codeplex.com/SourceControl/changeset/view/71473#1272188)
public IEnumerable<Message> GetRecentMessages(int moduleId, int hoursBackInTime, int maxRecords)
{
var messages = (from a in this.GetMessages(moduleId) where a.MessageDate.Subtract(DateTime.UtcNow).TotalHours <= hoursBackInTime select a).Take(maxRecords).Reverse();
return messages.Any() ? messages : null;
}
That is one approach, you can also use a SQL statement within the controller as well (http://signalrchat.codeplex.com/SourceControl/changeset/view/71473#1272186)
public ConnectionRecord GetConnectionRecordByConnectionId(string connectionId)
{
ConnectionRecord t;
using (IDataContext ctx = DataContext.Instance())
{
var connections = ctx.ExecuteQuery<ConnectionRecord>(CommandType.Text,
string.Format(
"select top 1 * from {0}{1}SignalRChat_ConnectionRecords where ConnectionId = '{2}'",
_databaseOwner,
_objectQualifier,
connectionId)).ToList();
if (connections.Any())
{
t = connections[0];
}
else
return null;
}
return t;
}
I'm switching over from structure map to Autofac. I've use a caching pattern from Scott Millett's book ASP.net Design Patterns which implements an interface for both Cache and the Repository and switches in the appropriate object depending on the constructor parameter name
The interface looks like this
public interface ISchemeRepository
{
List<Scheme> GetSchemes();
}
The cache object looks like this
public class SchemeRepository : BaseRepository, ISchemeRepository
{
/***************************************************************
* Properties
***************************************************************/
private readonly ISchemeRepository schemeRepository;
/***************************************************************
* Constructors
***************************************************************/
public SchemeRepository()
: this(ObjectFactory.GetInstance<ISchemeRepository>(), ObjectFactory.GetInstance<IConfigurationSetting>())
{
}
public SchemeRepository(ISchemeRepository realSchemeRepository, IConfigurationSetting configurationSetting)
{
schemeRepository = realSchemeRepository;
this.configurationSetting = configurationSetting;
}
/**************************************************************
* Methods
***************************************************************/
public List<Scheme> GetSchemes()
{
string key = Prefix + "Schemes";
if (!MemoryCache.Default.Contains(key))
{
MemoryCache.Default.Add(key, schemeRepository.GetSchemes(), new CacheItemPolicy());
}
return (List<Scheme>)MemoryCache.Default.Get(key);
}
}
The repository looks like this
public class SchemeRepository : BaseLocalRepository, ISchemeRepository
{
/***************************************************************
* Properties
***************************************************************/
private readonly IConnectionSetting connectionSetting;
/***************************************************************
* Constructors
***************************************************************/
public SchemeRepository()
: this(ObjectFactory.GetInstance<IConnectionSetting>())
{
}
public SchemeRepository(IConnectionSetting connectionSetting)
{
this.connectionSetting = connectionSetting;
}
/**************************************************************
* Methods
***************************************************************/
public List<Scheme> GetSchemes()
{
var response = new List<Scheme>();
var conn = new SqlConnection(connectionSetting.CQBConnectionString);
var command = new SqlCommand("proc_GetSchemes", conn) { CommandType = CommandType.StoredProcedure };
conn.Open();
var reader = command.ExecuteReader();
while (reader.Read())
{
response.Add(
new Scheme
{
SchemeId = reader["Scheme_Id"].ToString().Trim(),
GuaranteeText = reader["Guarantee_Text"].ToString().Trim()
}
);
}
conn.Close();
return response;
}
}
The structure map call is below
InstanceOf<Repository.Local.Contract.IProviderRepository>().Is.OfConcreteType<Repository.Local.Core.ProviderRepository>().WithName("RealProviderRepository");
ForRequestedType<Repository.Local.Contract.IProviderRepository>().TheDefault.Is.OfConcreteType<Repository.Local.Cache.ProviderRepository>().CtorDependency<Repository.Local.Contract.IProviderRepository>().Is(x => x.TheInstanceNamed("RealProviderRepository"));
Structure map looks at the constructor and if it contains a parameter called "realSchemeRepository" then it implements the object that connect to the database, if not it implements the cache object that checks the cache and calls the database if nothing is in the cache and populates the cache.
How do I do this in Autofac? Is there a better way of doing this in Autofac?
I believe what you're asking how to do is set up a decorator between your two repository classes. I'm gonna pretend the two class names are CacheSchemeRepository and RealSchemeRepository because naming them exactly the same is confusing and terrible. Anyways...
builder.Register(c => new RealSchemeRepository(c.Resolve<IConnectionSetting>())
.Named<ISchemeRepository>("real");
builder.RegisterDecorator<ISchemeRepository>(
(c, inner) => new CacheSchemeRepository(inner, c.Resolve<IConfigurationSetting>()),
"real");
I have read lots of information about page caching and partial page caching in a MVC application. However, I would like to know how you would cache data.
In my scenario I will be using LINQ to Entities (entity framework). On the first call to GetNames (or whatever the method is) I want to grab the data from the database. I want to save the results in cache and on the second call to use the cached version if it exists.
Can anyone show an example of how this would work, where this should be implemented (model?) and if it would work.
I have seen this done in traditional ASP.NET apps , typically for very static data.
Here's a nice and simple cache helper class/service I use:
using System.Runtime.Caching;
public class InMemoryCache: ICacheService
{
public T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class
{
T item = MemoryCache.Default.Get(cacheKey) as T;
if (item == null)
{
item = getItemCallback();
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(10));
}
return item;
}
}
interface ICacheService
{
T GetOrSet<T>(string cacheKey, Func<T> getItemCallback) where T : class;
}
Usage:
cacheProvider.GetOrSet("cache key", (delegate method if cache is empty));
Cache provider will check if there's anything by the name of "cache id" in the cache, and if there's not, it will call a delegate method to fetch data and store it in cache.
Example:
var products=cacheService.GetOrSet("catalog.products", ()=>productRepository.GetAll())
Reference the System.Web dll in your model and use System.Web.Caching.Cache
public string[] GetNames()
{
string[] names = Cache["names"] as string[];
if(names == null) //not in cache
{
names = DB.GetNames();
Cache["names"] = names;
}
return names;
}
A bit simplified but I guess that would work. This is not MVC specific and I have always used this method for caching data.
I'm referring to TT's post and suggest the following approach:
Reference the System.Web dll in your model and use System.Web.Caching.Cache
public string[] GetNames()
{
var noms = Cache["names"];
if(noms == null)
{
noms = DB.GetNames();
Cache["names"] = noms;
}
return ((string[])noms);
}
You should not return a value re-read from the cache, since you'll never know if at that specific moment it is still in the cache. Even if you inserted it in the statement before, it might already be gone or has never been added to the cache - you just don't know.
So you add the data read from the database and return it directly, not re-reading from the cache.
For .NET 4.5+ framework
add reference: System.Runtime.Caching
add using statement:
using System.Runtime.Caching;
public string[] GetNames()
{
var noms = System.Runtime.Caching.MemoryCache.Default["names"];
if(noms == null)
{
noms = DB.GetNames();
System.Runtime.Caching.MemoryCache.Default["names"] = noms;
}
return ((string[])noms);
}
In the .NET Framework 3.5 and earlier versions, ASP.NET provided an in-memory cache implementation in the System.Web.Caching namespace. In previous versions of the .NET Framework, caching was available only in the System.Web namespace and therefore required a dependency on ASP.NET classes. In the .NET Framework 4, the System.Runtime.Caching namespace contains APIs that are designed for both Web and non-Web applications.
More info:
https://msdn.microsoft.com/en-us/library/dd997357(v=vs.110).aspx
https://learn.microsoft.com/en-us/dotnet/framework/performance/caching-in-net-framework-applications
Steve Smith did two great blog posts which demonstrate how to use his CachedRepository pattern in ASP.NET MVC. It uses the repository pattern effectively and allows you to get caching without having to change your existing code.
http://ardalis.com/Introducing-the-CachedRepository-Pattern
http://ardalis.com/building-a-cachedrepository-via-strategy-pattern
In these two posts he shows you how to set up this pattern and also explains why it is useful. By using this pattern you get caching without your existing code seeing any of the caching logic. Essentially you use the cached repository as if it were any other repository.
I have used it in this way and it works for me.
https://msdn.microsoft.com/en-us/library/system.web.caching.cache.add(v=vs.110).aspx
parameters info for system.web.caching.cache.add.
public string GetInfo()
{
string name = string.Empty;
if(System.Web.HttpContext.Current.Cache["KeyName"] == null)
{
name = GetNameMethod();
System.Web.HttpContext.Current.Cache.Add("KeyName", name, null, DateTime.Noew.AddMinutes(5), Cache.NoSlidingExpiration, CacheitemPriority.AboveNormal, null);
}
else
{
name = System.Web.HttpContext.Current.Cache["KeyName"] as string;
}
return name;
}
AppFabric Caching is distributed and an in-memory caching technic that stores data in key-value pairs using physical memory across multiple servers. AppFabric provides performance and scalability improvements for .NET Framework applications. Concepts and Architecture
Extending #Hrvoje Hudo's answer...
Code:
using System;
using System.Runtime.Caching;
public class InMemoryCache : ICacheService
{
public TValue Get<TValue>(string cacheKey, int durationInMinutes, Func<TValue> getItemCallback) where TValue : class
{
TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
if (item == null)
{
item = getItemCallback();
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
}
return item;
}
public TValue Get<TValue, TId>(string cacheKeyFormat, TId id, int durationInMinutes, Func<TId, TValue> getItemCallback) where TValue : class
{
string cacheKey = string.Format(cacheKeyFormat, id);
TValue item = MemoryCache.Default.Get(cacheKey) as TValue;
if (item == null)
{
item = getItemCallback(id);
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.AddMinutes(durationInMinutes));
}
return item;
}
}
interface ICacheService
{
TValue Get<TValue>(string cacheKey, Func<TValue> getItemCallback) where TValue : class;
TValue Get<TValue, TId>(string cacheKeyFormat, TId id, Func<TId, TValue> getItemCallback) where TValue : class;
}
Examples
Single item caching (when each item is cached based on its ID because caching the entire catalog for the item type would be too intensive).
Product product = cache.Get("product_{0}", productId, 10, productData.getProductById);
Caching all of something
IEnumerable<Categories> categories = cache.Get("categories", 20, categoryData.getCategories);
Why TId
The second helper is especially nice because most data keys are not composite. Additional methods could be added if you use composite keys often. In this way you avoid doing all sorts of string concatenation or string.Formats to get the key to pass to the cache helper. It also makes passing the data access method easier because you don't have to pass the ID into the wrapper method... the whole thing becomes very terse and consistant for the majority of use cases.
Here's an improvement to Hrvoje Hudo's answer. This implementation has a couple of key improvements:
Cache keys are created automatically based on the function to update data and the object passed in that specifies dependencies
Pass in time span for any cache duration
Uses a lock for thread safety
Note that this has a dependency on Newtonsoft.Json to serialize the dependsOn object, but that can be easily swapped out for any other serialization method.
ICache.cs
public interface ICache
{
T GetOrSet<T>(Func<T> getItemCallback, object dependsOn, TimeSpan duration) where T : class;
}
InMemoryCache.cs
using System;
using System.Reflection;
using System.Runtime.Caching;
using Newtonsoft.Json;
public class InMemoryCache : ICache
{
private static readonly object CacheLockObject = new object();
public T GetOrSet<T>(Func<T> getItemCallback, object dependsOn, TimeSpan duration) where T : class
{
string cacheKey = GetCacheKey(getItemCallback, dependsOn);
T item = MemoryCache.Default.Get(cacheKey) as T;
if (item == null)
{
lock (CacheLockObject)
{
item = getItemCallback();
MemoryCache.Default.Add(cacheKey, item, DateTime.Now.Add(duration));
}
}
return item;
}
private string GetCacheKey<T>(Func<T> itemCallback, object dependsOn) where T: class
{
var serializedDependants = JsonConvert.SerializeObject(dependsOn);
var methodType = itemCallback.GetType();
return methodType.FullName + serializedDependants;
}
}
Usage:
var order = _cache.GetOrSet(
() => _session.Set<Order>().SingleOrDefault(o => o.Id == orderId)
, new { id = orderId }
, new TimeSpan(0, 10, 0)
);
public sealed class CacheManager
{
private static volatile CacheManager instance;
private static object syncRoot = new Object();
private ObjectCache cache = null;
private CacheItemPolicy defaultCacheItemPolicy = null;
private CacheEntryRemovedCallback callback = null;
private bool allowCache = true;
private CacheManager()
{
cache = MemoryCache.Default;
callback = new CacheEntryRemovedCallback(this.CachedItemRemovedCallback);
defaultCacheItemPolicy = new CacheItemPolicy();
defaultCacheItemPolicy.AbsoluteExpiration = DateTime.Now.AddHours(1.0);
defaultCacheItemPolicy.RemovedCallback = callback;
allowCache = StringUtils.Str2Bool(ConfigurationManager.AppSettings["AllowCache"]); ;
}
public static CacheManager Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
{
instance = new CacheManager();
}
}
}
return instance;
}
}
public IEnumerable GetCache(String Key)
{
if (Key == null || !allowCache)
{
return null;
}
try
{
String Key_ = Key;
if (cache.Contains(Key_))
{
return (IEnumerable)cache.Get(Key_);
}
else
{
return null;
}
}
catch (Exception)
{
return null;
}
}
public void ClearCache(string key)
{
AddCache(key, null);
}
public bool AddCache(String Key, IEnumerable data, CacheItemPolicy cacheItemPolicy = null)
{
if (!allowCache) return true;
try
{
if (Key == null)
{
return false;
}
if (cacheItemPolicy == null)
{
cacheItemPolicy = defaultCacheItemPolicy;
}
String Key_ = Key;
lock (Key_)
{
return cache.Add(Key_, data, cacheItemPolicy);
}
}
catch (Exception)
{
return false;
}
}
private void CachedItemRemovedCallback(CacheEntryRemovedArguments arguments)
{
String strLog = String.Concat("Reason: ", arguments.RemovedReason.ToString(), " | Key-Name: ", arguments.CacheItem.Key, " | Value-Object: ", arguments.CacheItem.Value.ToString());
LogManager.Instance.Info(strLog);
}
}
I use two classes. First one the cache core object:
public class Cacher<TValue>
where TValue : class
{
#region Properties
private Func<TValue> _init;
public string Key { get; private set; }
public TValue Value
{
get
{
var item = HttpRuntime.Cache.Get(Key) as TValue;
if (item == null)
{
item = _init();
HttpContext.Current.Cache.Insert(Key, item);
}
return item;
}
}
#endregion
#region Constructor
public Cacher(string key, Func<TValue> init)
{
Key = key;
_init = init;
}
#endregion
#region Methods
public void Refresh()
{
HttpRuntime.Cache.Remove(Key);
}
#endregion
}
Second one is list of cache objects:
public static class Caches
{
static Caches()
{
Languages = new Cacher<IEnumerable<Language>>("Languages", () =>
{
using (var context = new WordsContext())
{
return context.Languages.ToList();
}
});
}
public static Cacher<IEnumerable<Language>> Languages { get; private set; }
}
I will say implementing Singleton on this persisting data issue can be a solution for this matter in case you find previous solutions much complicated
public class GPDataDictionary
{
private Dictionary<string, object> configDictionary = new Dictionary<string, object>();
/// <summary>
/// Configuration values dictionary
/// </summary>
public Dictionary<string, object> ConfigDictionary
{
get { return configDictionary; }
}
private static GPDataDictionary instance;
public static GPDataDictionary Instance
{
get
{
if (instance == null)
{
instance = new GPDataDictionary();
}
return instance;
}
}
// private constructor
private GPDataDictionary() { }
} // singleton
HttpContext.Current.Cache.Insert("subjectlist", subjectlist);
You can also try and use the caching built into ASP MVC:
Add the following attribute to the controller method you'd like to cache:
[OutputCache(Duration=10)]
In this case the ActionResult of this will be cached for 10 seconds.
More on this here