使用实体框架的Azure函数返回空结果

时间:2018-08-16 23:06:18

标签: c# azure entity-framework-6 azure-functions azure-eventgrid

我正在编写一个Azure函数,该函数订阅事件网格,并在收到的每个事件上针对Azure SQL数据库执行操作。当一个系统“ SecondAppName”中发生由另一系统“ Appname”触发的创建错误时,事件网格将向其发布事件。基本上,在一个系统中创建一个实体,然后在另一个系统中创建一个类似的实体(也通过事件网格发布/订阅者)。此功能应用程序在第二个系统中查找创建失败,因此可以重新触发创建。这还没有完成,但是我遇到了障碍

我正在使用Entity Framework 6(数据库优先)从数据库读取和写入。尝试使用Entity Framework FindAsync()查询项目时,结果带回为null。这是相关代码,其中我组织的名称被遮盖了:

#r "Newtonsoft.Json"
#r "System.Configuration"
#r "System.Data"
#r "System.Data.Common"

using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections;
using System.Configuration;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Data.Entity.SqlServer;
using System.Data.SqlClient;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;

public static async Task Run(JObject eventGridEvent, TraceWriter log)
{
    log.Info($"event was: {eventGridEvent.ToString(Formatting.Indented)}");
    var eventGridEventProperties = eventGridEvent.Properties().ToList();
    if(
        eventGridEventProperties.Count(
            prop => prop.Name == "eventType" && prop.Value.ToString() == "error"
        ) > 0 &&
        eventGridEventProperties.Count(
            prop => prop.Name == "subject" && prop.Value.ToString() == "/appname/subject1"
        ) > 0
    )
    {
        var appnameSecondAppNameErrorEvent = eventGridEvent.ToObject<AppnameSecondAppNameErrorEvent>();
        var entityId = appnameSecondAppNameErrorEvent.Data.EntityId;
        log.Info($"subject1 create event error found for UAT Entity {entityId}");
        log.Info($"trying to query entity data for UAT Entity {entityId}");

        try
        {
            string connectionString = ConfigurationManager.ConnectionStrings["AppnameContext"].ToString();
            using (var _appnameContext = new AppnameDbContext(connectionString))
            {
                var entity = await _appnameContext.Entity.FindAsync(entityId)
                // var enitty = await _appnameContext
                //     .Entity
                //     .SqlQuery("select * from Entity where EntityId=@id", new SqlParameter("@id", entityId))
                //     .FirstOrDefaultAsync();

                if(entity != null)
                {
                    log.Info(
                        $@"Entity was Id: {entity.EntityId}, 
                           Name: {entity.Name}, 
                           Property1: {entity.Property1Name}, 
                           Property2Name: {entity.Property2Name}"
                    );
                }
                else
                {
                    throw new Exception($"UAT Entity {entityId} not found");
                }

            }
        }
        catch (Exception ex)
        {
            log.Info($"Error getting Appname UAT Entity {entityId} with reason: {ex.Message}");
        }
    }
}

public class AppnameSecondAppNameErrorEvent
{
    public Guid Id { get; set; }
    public string Subject { get; set; }
    public string EventType { get; set; }
    public DateTime EventTime { get; set; }
    public AppnameSecondAppNameErrorEventData Data { get; set; }
    public string DataVersion { get; set; }
    public string MetaDataVersion { get; set; }
    public string Topic { get; set; }
}

public class AppnameSecondAppNameErrorEventData
{
    public Guid EntityId { get; set; }
    public string ErrorMessage { get; set; }
}

public class AppnameDbContext : DbContext
{
    public AppnameDbContext(string cs) : base(cs) { }
    public DbSet<Entity> Entity { get;set; }
}

public class Entity
{
    [Key]
    public Guid EntityId { get; set; }
    public string Name { get; set; }
    public string Property1Name { get; set; }
    public string Property2Name { get; set; }
}

它总是抛出该异常“未找到UAT实体...”,因为该实体始终为空

我知道这不是连接问题,因为运行手动SQL查询的注释掉的代码行会带回结果。这也意味着结果也存在于数据库中。此外,如果我运行如下代码:

 var entity = await _appnameContext
                        .Entity
                        .SqlQuery("select * from Entity where EntityId=@id", new SqlParameter("@id", entityId))
                        .FirstOrDefaultAsync();
var entity2 = await _appnameContext.Entity.FindAsync(entityId);

entity2中包含结果,因此它已附加到上下文。

我在这里做错了什么?如果必须手动运行SQL查询才能使其正常工作,我什至不使用Entity Framework

以下是有关功能应用程序的更多相关信息:

project.json:

{
    "frameworks": {
        "net46":{
            "dependencies": {
                "EntityFramework": "6.1.2",
                "System.Data.Common": "4.3.0"
            }
        }
    }
}

功能应用程序设置中的连接字符串(组织细节和凭据被遮盖):

Server=tcp:server.database.windows.net,1433;Initial Catalog=DATABASE;Persist Security Info=False;User ID=username;Password=password;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;

该数据库的用户是管理员。

下面是发生的事件的示例:

{
    "id": "621ed36b-13df-4af3-af45-3cff2434cea7",
    "subject": "/appname/subject1",
    "eventType": "error",
    "eventTime": "2018-08-14T17:30:59.4395766Z",
    "data": {
        "entityId": "67d14894-1a0c-4c6d-b091-544260d89642",
        "errorMessage": "Error creating the entity"
    },
    "dataVersion": "",
    "metadataVersion": "1",
    "topic": "/subscriptions/..."
}

最后值得一提的是,我没有使用Visual Studio对此进行编程,而是使用Azure门户的Web界面进行编程。

感谢您的帮助或建议!

1 个答案:

答案 0 :(得分:0)

我发现了问题。以某种方式,实体框架首先执行了代码迁移,并添加了另一个表“ Entity1”,该表正从中查询。为了解决这个问题,我删除了新表,并在实体类上方添加了数据注释[Table("Entity")]