Trying to set up a Dapper-based Data Access Layer. ABP.Dapper documentation is confusing and incomplete - dapper

I'm trying to set up a simple DAL that will return a List of typed objects. Pretty standard data repository stuff. I downloaded all of ABP's code from GitHub, built the DLLs for Abp.Dapper and Abp.EntityFrameworkCore and started following the instructions on this page:
https://aspnetboilerplate.com/Pages/Documents/Dapper-Integration
But I can't even get past step one of this. This code doesn't compile because it doesn't know what SampleApplicationModule is. But there's no guidance in these instructions as to what that is supposed to be.
How am I supposed to use Abp's libraries? I'm lost. Can someone please let me know the minimum number of things I need to do in order to wire up my database to Abp's library and query for a List of typed objects?
Code from Abp's Dapper Integration documentation:
[DependsOn(
typeof(AbpEntityFrameworkCoreModule),
typeof(AbpDapperModule)
)]
public class MyModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(typeof(SampleApplicationModule).GetAssembly());
}
}

if you are confused what to write for SampleApplicationModule use the below code
Module Registration
[DependsOn(
typeof(AbpEntityFrameworkModule),
typeof(AbpKernelModule),
typeof(AbpDapperModule)
)]
public class SampleApplicationModule : AbpModule
{
public override void Initialize()
{
IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
}
}
Usage
public class SomeDomainService : ITransientDependency
{
private readonly IDapperRepository<Animal> _animalDapperRepository;
private readonly IRepository<Animal> _animalRepository;
private readonly IDapperRepository<Person> _personDapperRepository;
private readonly IRepository<Person> _personRepository;
private readonly IUnitOfWorkManager _unitOfWorkManager;
public SomeDomainService(
IUnitOfWorkManager unitOfWorkManager,
IRepository<Person> personRepository,
IRepository<Animal> animalRepository,
IDapperRepository<Person> personDapperRepository,
IDapperRepository<Animal> animalDapperRepository)
{
_unitOfWorkManager = unitOfWorkManager;
_personRepository = personRepository;
_animalRepository = animalRepository;
_personDapperRepository = personDapperRepository;
_animalDapperRepository = animalDapperRepository;
}
public void DoSomeStuff()
{
using (IUnitOfWorkCompleteHandle uow = _unitOfWorkManager.Begin())
{
_personRepository.Insert(new Person("Oğuzhan"));
_personRepository.Insert(new Person("Bread"));
_animalRepository.Insert(new Animal("Bird"));
_animalRepository.Insert(new Animal("Cat"));
_unitOfWorkManager.Current.SaveChanges();
Animal animal = _animalRepository.FirstOrDefault(x => x.Name == "Bird");
Person person = _personDapperRepository.Get(1);
int personCount = _personDapperRepository.Count(x => x.Name == "Oğuzhan");
List<Animal> persons = _animalDapperRepository.GetList(x => x.Name.StartsWith("O")).ToList();
uow.Complete();
}
}
}
See the related post for AbpDapper
https://github.com/aspnetboilerplate/aspnetboilerplate/pull/1854#issuecomment-284511423
PS: Abp.Dapper integration is implemented by the community.

Related

Is there any way that could help me select specific data from table in Microsoft.AspNetCore.Datasync.EFCore

Am learning about data sync from API to WPF app. Got a demo from https://github.com/Azure/azure-mobile-apps/tree/main/samples. But I got into a problem that all the data inside the tables are collected on the call but I need to select specific data using Id. Tried a query etc all came to nothing. Please guide me
Thank you
PatientsController.cs
[Route("tables/Patients")]
public class PatientsController : TableController<Patients>
{
public PatientsController(AppDbContext context)
: base(new EntityTableRepository<Patients>(context))
{
}
}
AppDbContext.cs
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
public DbSet<Patients> Patients => Set<Patients>();
}
Try to use the following code:
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options)
{
}
public DbSet<Patients> Patients {get;set;}
}
controller:
[Route("tables/Patients")]
public class PatientsController : TableController<Patients>
{
private readonly AppDbContext _context;
public PatientsController(AppDbContext context)
: base(new EntityTableRepository<Patients>(context))
{
_context=context;
}
public async Task<IActionResult> Index(int id){
var Patients=_context.Patients.FindAsync(id);
return View(Patients);
}
}
If you just need to get a record by Id, you use the URL https://mysite/tables/myTable/id - no search required - it will go directly to the entity you want.
If you need to limit what a user can see, you will need to implement an access control provider (which is an implementation of IAccessControlProvider). This provides three methods to limit what a user can see and do model updates for ensuring the write operations store the right thing. You can read more here: https://learn.microsoft.com/en-us/azure/developer/mobile-apps/azure-mobile-apps/howto/server/dotnet-core#configure-access-permissions
If it's something else, you'll need to be a little more specific. I hang out in the issues and discussions of the azure/azure-mobile-apps repo, so feel free to file a question there.

How can I access HttpContext Header values in Static class

I am programming an ASP.NET Core 5.0 Web API.
I have a CurrentUser class like this. I want to access the header info anywhere in the project by using CurrentUser.Id. How can I do that? (or where can I initialize httpContext variable?)
public class CurrentUser
{
private static HttpContext _context;
private static UserDto _myUserObj;
public static void Initialize(AuthorizationFilterContext context)
{
_context = context.HttpContext;
_myUserObj = context.HttpContext.Request.Headers["User"] as UserDto;
}
public static int Id()
{
return _myUserObj.Id
}
}
I found some solutions. But I think its not best practice solutions. (There must be another and better way..)
MySolutions is that:
I am building a custom Attribute and i am adding it every API Controller like this:
[MyCustomAttribute]
public class UserController : ControllerBase{
//blablabla
}
After this : I am setting my CurrentUser.Initilaze() method in this Attribute like this:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class MyCustomAttribute: Attribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationFilterContext context)
{
//fortest
var userObj = context.HttpContext.Request.Headers["User"];//working
var userObj2 = JsonSerializer.Deserialize<UserDto>(userObj, new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
});//working
CurrentUser.Initialize(context);//working
var testResult = CurrentUser.Test();//working
}
}
So I can use CurrentUser static class everywhere in N-Layerd project and I am accessing UserId or another variables..
But i am saying again, I think its not best solution. Because I have to add [MyCustomAttribute] to all Controllers. There must be a better solition.

Objectify Ref<> with #Load is not working with ofy().load().group()

I have a problem Ref<> usage with #Load. Basically I made a copy paste from Objectify website to test #Load annotation with Load Groups.
#Entity
public static class Thing {
public static class Partial {}
public static class Everything extends Partial {}
public static class Stopper {}
#Id Long id;
#Load(Partial.class) Ref<Other> withPartial;
#Load(Everything.class) Ref<Other> withEveryhthing;
#Load(unless=Stopper.class) Ref<Other> unlessStopper;
public Ref<Other> getWithPartial() {
return withPartial;
}
public void setWithPartial(Ref<Other> withPartial) {
this.withPartial = withPartial;
}
public Ref<Other> getWithEveryhthing() {
return withEveryhthing;
}
public void setWithEveryhthing(Ref<Other> withEveryhthing) {
this.withEveryhthing = withEveryhthing;
}
public Ref<Other> getUnlessStopper() {
return unlessStopper;
}
public void setUnlessStopper(Ref<Other> unlessStopper) {
this.unlessStopper = unlessStopper;
}
}
Then I wrote the following code.
Other other = new Other();
Key<Other> otherKey = ofy().save().entity(other).now();
Thing thing = new Thing();
thing.setWithPartial(Ref.create(otherKey));
Key<Thing> thingKey = ofy().save().entity(thing).now();
Thing t = ofy().load().key(thingKey).now();
System.out.println("Is loaded: " + t.getWithPartial().isLoaded());
Without writing ofy().load().group(Partial.class).key(thingKey).now(); other entity still loads into session. However in documentation it needs group class to be loaded.
The isLoaded() method tests whether the entity is in the session cache. Since you just save()d the entity, it's already in the session cache.
If you want to test the behavior of load groups, you need to ofy().clear() the cache.

WPF how to use DesignerProperties.IsInDesignTool to solve a design time error "cannot create an instance"?

I have the following class that I use in order to populate a combo box:
public class DamageTypeList
{
static Begbil2Entities _DB = new Begbil2Entities();
public static List<HUB_DamageTypes> _list = (from d in _DB.HUB_DamageTypes orderby d.DamageOrder select d).ToList();
public static List<HUB_DamageTypes> TList
{
get
{
return _list;
}
}
}
In the xaml file I add it like this:
<UserControl.Resources>
<me:DamageTypeList x:Key="DamageTypeList"/>
The xaml line creates an error (ONLY in design time, it runs pefectly at runtime):
Cannot create an instance of "DamageTypeList". C:\HUB\HUB\HubbCostOfferPage.xaml
I have found some suggestions to solve it by using:
if (!DesignerProperties.IsInDesignTool)
But how do I use it to solve my problem?
You can use the flag DesignerProperties.IsInDesignTool to prevent the DB creation and to use hardcoded entities in your list.
public class DamageTypeList
{
static Begbil2Entities _DB;
public static List<HUB_DamageTypes> _list;
public static Begbil2Entities DB
{
get
{
if(_DB == null && !DesignerProperties.IsInDesignTool)
_DB = new Begbil2Entities();
return _DB;
}
}
public static List<HUB_DamageTypes> TList
{
get
{
if(_list == null)
{
if(!DesignerProperties.IsInDesignTool)
_list = (from d in DB.HUB_DamageTypes orderby d.DamageOrder select d).ToList();
else
_list = new List<HUB_DamageTypes>(){
// Initialize it with hardcoded values
};
}
return _list;
}
}
}
Before doing that, tough, I would investigate a little further what is the cause of the design-time exception, as #fhlamarche suggested. You can try to debug the design time execution, is not that hard. See this link.
The designer attempts to call the default constructor but your class doesn't have one.
You just need to add a private or internal default constructor to your class.

Dynamic Autosuggest Combobox in GXT

Over the past 5 months we have been prototyping GWT and setting up the infrastructure. WE are using GXT for the widgets with MVP and Command Pattern implementations. However, we are currently looking to do a spike on a ComboBox with autosuggest from a live Database. I would like to do this in the framework of the MVP and Command pattern implementations. Any one out there have any ideas how to go about doing this?
I solved that using a generic DispatchDataProxy modelled over the Command Pattern. Thanks for the link, but GXT documentation leaves a lot to be desired, though the framework is really nice and cool.
I will post the code here `public class DispatchDataProxy implements DataProxy> {
#Inject
private DispatchAsync dispatch ;//= new StandardDispatchAsync(new DefaultExceptionHandler());
#Override
public void load(DataReader<ListLoadResult<X>> reader, Object loadConfig, final AsyncCallback<ListLoadResult<X>> callback) {
if (loadConfig instanceof BasePagingLoadConfig) {
BasePagingLoadConfig a = (BasePagingLoadConfig) loadConfig;
Map<String, Object> map = a.getProperties();
Object data = map.get("query");
XCommand action = new XCommand();
action.setX((String) data);
dispatch.execute(action, new AsyncCallback<XResult>() {
#Override
public void onFailure(Throwable arg0) {
//Log.debug("Some error:" + arg0.getMessage());
callback.onFailure(arg0);
}
#Override
public void onSuccess(XResult arg0) {
ListLoadResult<X> list = arg0.getList();
callback.onSuccess(list);
}
});
}
}
public DispatchAsync getDispatch() {
return dispatch;
}
public void setDispatch(DispatchAsync dispatch) {
this.dispatch = dispatch;
}
}`
Hope its useful. Will appreciate some comments as well
Have you looked here?
http://www.sencha.com/examples-2/explorer.html#advancedcombobox
They show something similar. The issue with GXT is you are better off using their DataProxy because you need to set a ModelData instance.
I found solution for simple combo box, override getValue method:
public SimpleComboBox<String> createEditableSimpleComboBox() {
return new SimpleComboBox<String>() {
#Override
public SimpleComboValue<String> getValue() {
SimpleComboValue<String> v = super.getValue();
String raw = getRawValue();
if ((v == null || v.getValue() == null) && raw != null && !raw.isEmpty()) {
v = new SimpleComboValue<String>(raw){
private static final long serialVersionUID = 1L;
};
}
return v;
}
};
}
Now when you add to combo box default value (not defined in store) method getValue returns this value - not null.

Resources