I am using nopCommerce 3.50. I have implementing plugin in nopCommerce. I have create stored procedure in SQL server. Now I want to create stored procedure from plugin by code. When plugin is installed, it will create stored procedure.
How can I create stored procedure from plugin in nopCommerce?
Refer to the stock plugin Nop.Plugin.Shipping.ByWeight
Your ObjectContext will have an Install() method, use that to create your stored procedure. Remove it in the Uninstall method.
public string CreateDatabaseScript()
{
return ((IObjectContextAdapter)this).ObjectContext.CreateDatabaseScript();
}
/// <summary>
/// Install
/// </summary>
public void Install()
{
//create the table
var dbScript = CreateDatabaseScript();
Database.ExecuteSqlCommand(dbScript);
SaveChanges();
}
/// <summary>
/// Uninstall
/// </summary>
public void Uninstall()
{
//drop the table
var tableName = this.GetTableName<ShippingByWeightRecord>();
//var tableName = "ShippingByWeight";
this.DropPluginTable(tableName);
}
Refer to Nop.Service.CAtalog.ProductService
var products = _dbContext.ExecuteStoredProcedureList<Product>(
"ProductLoadAllPaged",
pCategoryIds,
pManufacturerId,
pStoreId,
pVendorId,
pWarehouseId,
pParentGroupedProductId,
pProductTypeId,
pVisibleIndividuallyOnly,
pProductTagId,
pFeaturedProducts,
pPriceMin,
pPriceMax,
pKeywords,
pSearchDescriptions,
pSearchSku,
pSearchProductTags,
pUseFullTextSearch,
pFullTextMode,
pFilteredSpecs,
pLanguageId,
pOrderBy,
pAllowedCustomerRoleIds,
pPageIndex,
pPageSize,
pShowHidden,
pLoadFilterableSpecificationAttributeOptionIds,
pFilterableSpecificationAttributeOptionIds,
pTotalRecords);
It calls the productloadallpaged stored procedure.
This will work.
public class SearchEngineData : ISearchEngineData
{
private readonly IDbContext _dbContext;
public SearchEngineData(IDbContext dbContext){
_dbContext = dbContext;
}
private List<ElasticStoreMapping> GetStoreMappingsForProducts(int[] productIds)
{
var pProductIds = _dataProvider.GetParameter();
pProductIds.ParameterName = "ProductIds";
pProductIds.Value = productIds == null ? string.Empty : string.Join(",", productIds);
pProductIds.DbType = DbType.String;
return _dbContext.SqlQuery<ElasticStoreMapping>($"Exec GetStoreMappingForElastic #ProductIds", pProductIds).ToList();
}
}
Related
I am getting the handle on .NET Core 6 and I am stuck. I am using AutoMapper and I have dependency injection set up.
My implementation:
public class LSif : ISif
{
private readonly DataContext _db;
private readonly IMemoryCache _memoryCache;
public LSif(DataContext db, IMemoryCache memoryCache)
{
_db = db;
_memoryCache = memoryCache;
}
public List<DropDown> MjernaJedinicaDD(int selected)
{
string key = "MjernaJedinicaDD" + selected;
List<DropDown> dd = new List<DropDown>();
if (!_memoryCache.TryGetValue(key, out dd))
{
var model = GetAllMjernaJedinica();
if (model != null)
{
foreach (var item in model)
{
dd.Add(
new DropDown()
{
Id = item.Id,
Name = item.Name,
Selected = selected
}
);
}
}
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetSlidingExpiration(TimeSpan.FromSeconds(30));
_memoryCache.Set(key, dd, cacheEntryOptions);
}
return dd;
}
}
My goal is to call that implementation method from Automapper resolver:
.ForMember(d => d.MjernaJedinicaDD, o => o.MapFrom<MjernaJedinicaDDArtikal>());
And the resolver looks like this:
public class MjernaJedinicaDDArtikal : IValueResolver<Artikal, ArtikalVM, List<DropDown>>
{
public List<DropDown> Resolve(Artikal source, ArtikalVM destination, List<DropDown> member, ResolutionContext context)
{
var services = new ServiceCollection(); // With this i shoud work
services.AddScoped<ISif, LSif>(); // but i doesn't
using ServiceProvider serviceProvider = services.BuildServiceProvider(validateScopes: true);
using (IServiceScope scope = serviceProvider.CreateScope())
{
ISif reff = scope.ServiceProvider.GetRequiredService<ISif>();
if (reff != null)
{
return reff.MjernaJedinicaDD(source.MjernaId);
}
}
return null;
// This is how I did it in .NET Framework 4.5
var lSif = new LSif();
return lSif.MjernaJedinicaDD(source.MjernaId);
}
}
Question: how to instantiate / access class that has dependency injection components (parameters) form AutoMapper custom resolver?
Aditional info:
I initiate AutoMapper using
public interface IMapFrom<T>
{
void Mapping(Profile profile) => profile.CreateMap(typeof(T), GetType());
}
and then
public class AutoMapperProfile : Profile
{
public AutoMapperProfile()
{
ApplyMappingsFromAssembly(Assembly.GetExecutingAssembly());
}
private void ApplyMappingsFromAssembly(Assembly assembly)
{
var types = assembly.GetExportedTypes()
.Where(t => t.GetInterfaces().Any(i =>
i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IMapFrom<>)))
.ToList();
foreach (var type in types)
{
var instance = Activator.CreateInstance(type);
var methodInfo = type.GetMethod("Mapping") ??
type.GetInterface("IMapFrom`1").GetMethod("Mapping");
methodInfo?.Invoke(instance, new object[] { this });
}
}
}
and finaly in program.cs
builder.Services.AddAutoMapper(Assembly.GetExecutingAssembly());
When you call one of the AddAutoMapper extension methods on IServiceCollection provided by the NuGet package AutoMapper.Extensions.Microsoft.DependencyInjection during startup, this does several things including:
Adding your custom value resolver (e.g. MjernaJedinicaDDArtikal) to the dependency injection (DI) container
Configuring the Mapper to resolve dependencies from the container needed by your custom components that implement AutoMapper interfaces (such as IValueResolver)
(For additional details on what the AddAutoMapper method does, see the README for the NuGet package.)
This allows you to use constructor injection to directly supply the dependencies that your custom value resolver needs. These dependencies will be resolved from the DI container and they can also require other dependencies from the container themselves.
Your custom value resolver becomes:
public class MjernaJedinicaDDArtikal : IValueResolver<Artikal, ArtikalVM, List<DropDown>>
{
private readonly ISif _isif;
public MjernaJedinicaDDArtikal(ISif isif)
{
_isif = isif ?? throw new ArgumentNullException(nameof(isif));
}
public List<DropDown> Resolve(Artikal source, ArtikalVM destination, List<DropDown> member, ResolutionContext context)
{
return _isif.MjernaJedinicaDD(source.MjernaId);
}
}
Here is a simplified version of your AutoMapper profile that uses your custom value resolver:
public class AutoMapperProfile : Profile
{
public AutoMapperProfile()
{
CreateMap<Artikal, ArtikalVM>()
.ForMember(dest => dest.MjernaJedinicaDD, src => src.MapFrom<MjernaJedinicaDDArtikal>());
}
}
Finally, add your ISif service to the container using the LSif class as its implementation as well as any dependencies the LSif class needs.
When using the minimal hosting model for an ASP.NET Core app with .NET 6 or later, add the snippets below to Program.cs (some of the lines included with default .NET templates are included to provide context):
// TODO: add 'using' directives for namespace(s) containing ISif and LSif
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllersWithViews(); // or other similar method
// Register DataContext, which is injected into LSif
// TODO: Fill in app-specific implementation
// Register IMemoryCache implementation for injection into LSif
builder.Services.AddMemoryCache(options =>
{
// TODO: fill in desired cache options
});
// Register ISif service using LSif implementation
builder.Services.AddTransient<ISif, LSif>();
builder.Services.AddAutoMapper(Assembly.GetExecutingAssembly());
// ...
var app = builder.Build();
For other people that may want to use a similar approach but are using an earlier version of ASP.NET Core without the minimal hosting model (e.g. ASP.NET Core 3.1 or 5.0 with the Generic Host), add the custom service registrations to Startup.ConfigureServices(IServiceCollection) instead of adding them in Program.cs using builder.Services.AddXyz. For example:
public void ConfigureServices(IServiceCollection services)
{
// ...
// Register DataContext, which is injected into LSif
// TODO: Fill in app-specific implementation
// Register IMemoryCache implementation for injection into LSif
services.AddMemoryCache(options =>
{
// TODO: fill in desired cache options
});
// Register ISif service using LSif implementation
services.AddTransient<ISif, LSif>();
services.AddAutoMapper(Assembly.GetExecutingAssembly());
// ...
}
The way that AutoMapper can use the application's default DI container to resolve dependencies is that the AddAutoMapper extension method passes the IServiceProvider.GetService(Type) method as the serviceCtor argument to the Mapper constructor (source, v11.0.0).
Side note: You may also want to tweak your LSif.MjernaJedinicaDD method to avoid throwing a NullReferenceException on the line for dd.Add(...). After calling _memoryCache.TryGetValue(key, out dd), dd will be null when TryGetValue returns false because null is the default value for any C# reference type, such as a class, which List<T> is (reference).
I have a service inside an azure function
public MyService(
IConfigurationProvider configurationProvider,
ISerializationHelperService serializationHelperService,
ICommandListBuilder commandListBuilder,
[CosmosDB(
StaticSettings.Db,
StaticSettings.MyCollection.Collection,
ConnectionStringSetting = StaticSettings.DbConnectionStringSetting)] IDocumentClient documentClient)
{
//my logic here - this does get hit
}
My service is instantiated however, documentClient is null
How can I get this to be set properly? I dont get any errors
I have checked and there are no issues with the connection settings
public const string Db = "mydbname";
public const string DbConnectionStringSetting = "CosmosDBConnection";
public static class MyCollection
{
public const string Collection = "mycollectionname";
public static Uri CollectionUri => UriFactory.CreateDocumentCollectionUri(Db, Collection);
}
I am using a Startup class with an AddServices method to setup DI
Do I need to put something in there?
Paul
I have Azure function v2 project and I'm able to inject all my dependencies. Below lines added for IDocumentClient
string databaseEndPoint = Environment.GetEnvironmentVariable("DatabaseEndPoint");
string databaseKey = Environment.GetEnvironmentVariable("DatabaseKey");
builder.Services.AddSingleton<IDocumentClient>(new DocumentClient(new System.Uri(databaseEndPoint), databaseKey,
new ConnectionPolicy
{
ConnectionMode = ConnectionMode.Direct,
ConnectionProtocol = Protocol.Tcp,
RequestTimeout = TimeSpan.FromMinutes(5),//Groupasset sync has some timeout issue with large payload
// Customize retry options for Throttled requests
RetryOptions = new RetryOptions()
{
MaxRetryAttemptsOnThrottledRequests = 5,
MaxRetryWaitTimeInSeconds = 60
}
}
));
My Database Service
protected readonly IDocumentClient client;
protected BaseDao(IDocumentClient client)
{
this.client = client;
}
hope it will help!
basically I'm getting an exception while im performing this:
var userDb = new UserData();
userDb.InsertData(DbName);
My InsertData function:
var userRepo = new UserRepository();
var users = new List<User>();
using (var db = userRepo.InitialDb(dbName))
{
userRepo.AddList(_users);
users = userRepo.GetAll();
}
and while I'm running InsertData function, i get this exception:
{"Method not found: 'LiteDB.LiteDatabase Db.Data.Repository.Repository`1.InitialDb(System.String)'."}
My UserRepository.cs
public class UserRepository : Repository<User>{}
While my Repository.cs:
public abstract class Repository<T> where T : class
{
protected LiteDatabase db;
public LiteDatabase InitialDb(string dbPath)
{
db = new LiteDatabase(dbPath);
return db;
}
}
So the question here is,
1. I don't know if i inherited my parent well.
2. If yes, why there is a method not found exception thrown?
Thanks in advance, let me know if i missed out anything in the question.
I found this code here
using (var objCtx = new SchoolDBEntities())
{
var schoolCourse = from cs in objCtx.Courses
where cs.CourseName == "Course1"
select cs;
Course mathCourse = schoolCourse.FirstOrDefault<Course>();
IList<Course> courseList = schoolCourse.ToList<Course>();
string courseName = mathCourse.CourseName;
}
And I am using it in a Get method of a web api. When i use a using statement I get the following error
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection
I I do not use it, then how would I dispose of the context object responsibly?
I use something like this to solve the problem without resorting to eager loading (in fact usually in a generic abstract base controller that I extend, but this example is simplified):
public class MyController : ApiController
{
private SchoolDBEntities _objCtx;
// Singleton ObjectContext
protected SchoolDBEntities objCtx
{
if(_objCtx == null) _objCtx = new SchoolDBEntities();
return _objCtx;
}
// Use singleton objCtx without using wrapper here, in Get() or other methods.
public String Get()
{
var schoolCourse = from cs in objCtx.Courses
where cs.CourseName == "Course1"
select cs;
Course mathCourse = schoolCourse.FirstOrDefault<Course>();
string courseName = mathCourse.CourseName;
return courseName
}
// ApiController implements IDisposable, so you can override Dispose to do clean-up here.
// This is not called until the controller is disposed, so you won't get the error you report.
protected override void Dispose(Boolean disposing)
{
if (_objCtx!= null)
{
_objCtx.Dispose();
_objCtx = null;
}
base.Dispose(disposing);
}
}
I am new to MongoDB, and am trying to get the C# driver to work serializing F# classes. I have it working with the class automapper using mutable F# fields & a parameterless constructor, but really I need to retain immutability, so I started looking at implementing an IBsonSerializer to perform custom serialization. I haven't found any documentation for writing one of these so have just tried to infer from the driver source code.
I have run into a problem whereby when the Deserialize method is called on the serializer, the CurrentBsonType is set to EndOfDocument rather than the start as I am expecting. I wrote the equivalent in C# just to make sure it wasn't some F# weirdness, but the problem persists. The serialization part seems to work fine and is queryable from the shell. Here is the sample code:
class Calendar {
public string Id { get; private set; }
public DateTime[] Holidays { get; private set; }
public Calendar(string id, DateTime[] holidays) {
Id = id;
Holidays = holidays;
}
}
class CalendarSerializer : BsonBaseSerializer {
public override void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) {
var calendar = (Calendar) value;
bsonWriter.WriteStartDocument();
bsonWriter.WriteString("_id", calendar.Id);
bsonWriter.WriteName("holidays");
var ser = new ArraySerializer<DateTime>();
ser.Serialize(bsonWriter, typeof(DateTime[]), calendar.Holidays, null);
bsonWriter.WriteEndDocument();
}
public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options) {
if (nominalType != typeof(Calendar) || actualType != typeof(Calendar))
throw new BsonSerializationException();
if (bsonReader.CurrentBsonType != BsonType.Document)
throw new FileFormatException();
bsonReader.ReadStartDocument();
var id = bsonReader.ReadString("_id");
var ser = new ArraySerializer<DateTime>();
var holidays = (DateTime[])ser.Deserialize(bsonReader, typeof(DateTime[]), null);
bsonReader.ReadEndDocument();
return new Calendar(id, holidays);
}
public override bool GetDocumentId(object document, out object id, out Type idNominalType, out IIdGenerator idGenerator) {
var calendar = (Calendar) document;
id = calendar.Id;
idNominalType = typeof (string);
idGenerator = new StringObjectIdGenerator();
return true;
}
public override void SetDocumentId(object document, object id) {
throw new NotImplementedException("SetDocumentId is not implemented");
}
}
This blows up with FileFormatException in Deserialize when the CurrentBsonType is not Document. I am using the latest version 1.4 of the driver source.
I figured this out in the end. I should have used bsonReader.GetCurrentBsonType() instead of bsonReader.CurrentBsonType. This reads the BsonType in from the buffer rather than just looking at the last thing there. I also fixed a subsequent bug derserializing. The updated method looks like this:
public override object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, IBsonSerializationOptions options) {
if (nominalType != typeof(Calendar) || actualType != typeof(Calendar))
throw new BsonSerializationException();
if (bsonReader.GetCurrentBsonType() != BsonType.Document)
throw new FileFormatException();
bsonReader.ReadStartDocument();
var id = bsonReader.ReadString("_id");
bsonReader.ReadName();
var ser = new ArraySerializer<DateTime>();
var holidays = (DateTime[])ser.Deserialize(bsonReader, typeof(DateTime[]), null);
bsonReader.ReadEndDocument();
return new Calendar(id, holidays);
}