Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
4.1k views
in Technique[技术] by (71.8m points)

c# - How to add translations to database after API response with EF Core?

I have a requirement to add a project and translate its description with an external API translation service into several languages (so they exist in the database and it's possible to fetch a project in different languages later). Since translation takes quite some time - I first need to return the API response and then translate description and add additional locale rows to the database.
The db schema looks like this:
enter image description here
DB Context setup:

public class ProjectsContext : DbContext
{
    public ProjectsContext(DbContextOptions<ProjectsContext> options)
        : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder mb)
    {
        mb.Entity<Project>().ToTable("Project");
        mb.Entity<ProjectLocale>().ToTable("ProjectLocales")
            .HasKey(pl => new {pl.ProjectId, pl.Locale});
    }
    public DbSet<Project> Projects { get; set; }
}

In the Startup class, ConfigureServices method:

services.AddDbContext<ProjectsContext>(options =>
    options.UseMySql(envConfig.PROJECTS_DB_CONNECTION_STRING_MASTER));

The models:

public class Project
{
    public int Id { get; private set; }
    public List<ProjectLocale> ProjectLocales { get; private set; } = new List<ProjectLocale>();
    public async Task TranslateDescription(Translator translator, LanguageEnum currentLanguage)
    {
        ProjectLocales = await translator.Translate(ProjectLocales, currentLanguage);
    }
}
public class ProjectLocale
{
    public int ProjectId { get; set; }
    public string Locale { get; set; }
    public string Description { get; set; }
}

In the repository I have the following Add and AddProjectDescriptionTranslation methods:

public void Add(Project project)
{
    projectsContext.Projects.Add(project);
    projectsContext.SaveChanges();
    AddProjectDescriptionTranslations(project);
}

private async Task AddProjectDescriptionTranslations(Project project)
{
    await project.TranslateDescription(translator, headers.LanguageEnum);
    projectsContext.Projects.Update(project);
    projectsContext.SaveChanges();
}

I use Add method in the controller's POST method, and the next row is already returning the added project with the description in the current language. Translator and Headers are injected into my repository class.
The current solution gives me an error (that I can view only if I follow the async method execution with a breakpoint):

Cannot access a disposed object. A common cause of this error is disposing a context that was
resolved from dependency injection and then later trying to use the same context instance
elsewhere in your application. This may occur if you are calling Dispose() on the context,
or wrapping the context in a using statement. If you are using dependency injection, you should
let the dependency injection container take care of disposing context instances.
Object name: 'ProjectsContext'.

Is there any solution to this problem? Or maybe a better approach to achieve the same goal? I need the translations to be saved in the database after the response is given to the user in the current language (I receive the current language project's description from the frontend) to optimize the response time.

Thanks in advance for your time!


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It hard to say what you trying to achieve and how you are doing it, so this answer might be useless. I am not sure how you are disposing the context, but you have to make sure you dispose it after all the calls are made.

the most straightforward approach it to have

public async Task Add(Project project)
{
    using (var projectsContext= new ProjectsContext())
    {     
        // Perform data access using the context
    
        projectsContext.Projects.Add(project);
        projectsContext.SaveChanges();
        await AddProjectDescriptionTranslations(project, projectsContext);
     }
   }
}

private async Task AddProjectDescriptionTranslations(Project project, ProjectsContext projectsContext)
{
    await project.TranslateDescription(translator, headers.LanguageEnum);
    projectsContext.Projects.Update(project);
    projectsContext.SaveChanges();
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...